David Eyers
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invitee
    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Versions and GitHub Sync Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
Invitee
Publish Note

Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

Your note will be visible on your profile and discoverable by anyone.
Your note is now live.
This note is visible on your profile and discoverable online.
Everyone on the web can find and read all notes of this public team.
See published notes
Unpublish note
Please check the box to agree to the Community Guidelines.
View profile
Engagement control
Commenting
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Suggest edit
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
Emoji Reply
Enable
Import from Dropbox Google Drive Gist Clipboard
   owned this note    owned this note      
Published Linked with GitHub
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
## Lab 13—Kubernetes and AWS orchestration with CloudFormation This purpose of this lab is to provide you with potentially interesting starting points for your future exploration of cloud technologies beyond COSC349. :::info :bulb: The Kubernetes and CloudFormation parts of this lab are entirely independent so if you get blocked completing one part, you should be able to continue with the other. ::: ## Kubernetes :::warning :warning: Note that the Kubernetes exercise here will not work on Macs with M-series CPUs... but we're so close (days? weeks?): VirtualBox 7.1 provides the necessary support, but Vagrant hasn't been updated for VirtualBox 7.1 yet... ::: ### Installing Kubernetes - There are many ways to run Kubernetes infrastructure on AWS, as discussed in lectures... - ... however most of the more convenient approaches will not work using AWS Academy Learner Labs, due to missing management of permissions through IAM. - It is, of course, possible create a complete Kubernetes infrastructure just using EC2 nodes, but this is not how developers would typically build such a system. ### Minikube - We will use a special distribution of Kubernetes that is designed to be run on a single machine, in this case a VM provisioned on your computer using Vagrant. - The installation of Minikube is not automated, so that you can watch it progress. - Start by cloning the repository at: https://altitude.otago.ac.nz/cosc349/lab13-kubernetes - Provision the VM using `vagrant up`. - `vagrant ssh` into the VM. - On the VM, run the following two commands to download and then install Minikube within your VM (note that we're using a specific version of Minikube so that there's a higher chance these instructions cause reproducible effects): - For Intel-based CPUs, run: ``` curl -LO https://github.com/kubernetes/minikube/releases/download/v1.34.0/minikube_1.34.0-0_amd64.deb sudo dpkg -i minikube_1.34.0-0_amd64.deb ``` - For Arm-based CPUs, change `amd64` to `arm64` as in by running: ``` curl -LO https://github.com/kubernetes/minikube/releases/download/v1.34.0/minikube_1.34.0-0_arm64.deb sudo dpkg -i minikube_1.34.0-0_arm64.deb ``` - Now start Minikube with the following command: ``` minikube start ``` - You should see the system downloading the Docker images that it uses to drive the components of Kubernetes. (This will take some time to complete.) After a number of minutes, the output should resemble: ``` 😄 minikube v1.34.0 on Ubuntu 24.04 (vbox/amd64) ✨ Automatically selected the docker driver. Other choices: none, ssh 📌 Using Docker driver with root privileges 👍 Starting "minikube" primary control-plane node in "minikube" cluster 🚜 Pulling base image v0.0.45 ... 💾 Downloading Kubernetes v1.31.0 preload ... > preloaded-images-k8s-v18-v1...: 326.69 MiB / 326.69 MiB 100.00% 19.97 M > gcr.io/k8s-minikube/kicbase...: 487.89 MiB / 487.90 MiB 100.00% 19.67 M 🔥 Creating docker container (CPUs=2, Memory=2200MB) ... 🐳 Preparing Kubernetes v1.31.0 on Docker 27.2.0 ... ▪ Generating certificates and keys ... ▪ Booting up control plane ... ▪ Configuring RBAC rules ... 🔗 Configuring bridge CNI (Container Networking Interface) ... 🔎 Verifying Kubernetes components... ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5 🌟 Enabled addons: storage-provisioner, default-storageclass 💡 kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A' 🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default ``` ### Looking into your Kubernetes "cluster" - You can now examine your Kubernetes cluster, using the `kubectl` command. In our case we'll prepend `minikube` to these invocations and run the `kubectl` command on the Kubernetes control plane. You may be able to get `kubectl` to work directly, e.g., installing from the Ubuntu package repositories or similar. - List the nodes on your cluster (there should only be one): ``` minikube kubectl get nodes ``` - List the pods currently deployed (there shouldn't be any in your default namespace): ``` minikube kubectl get pods ``` - ... but there will be, if looking across all namespaces: ``` minikube kubectl -- get pods -A ``` - You can thus confirm that a significant amount of software infrastructure is already running, as the core of the Kubernetes platform. ### Opening up a web dashboard - Invoke the following command to start a web-dashboard. This invocation will occupy your SSH session, but you can open another terminal window and from it `vagrant ssh` in again. ``` sudo minikube dashboard ``` - After some delay, output such as the following should be presented: ``` 🔌 Enabling dashboard ... ▪ Using image docker.io/kubernetesui/dashboard:v2.7.0 ▪ Using image docker.io/kubernetesui/metrics-scraper:v1.0.8 💡 Some dashboard features require the metrics-server addon. To enable all features please run: minikube addons enable metrics-server 🤔 Verifying dashboard health ... 🚀 Launching proxy ... 🤔 Verifying proxy health ... 🎉 Opening http://127.0.0.1:32915/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser... 👉 http://127.0.0.1:32915/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ ``` - The URL will need to be opened on your host computer's web browser, which means that you will need to set up port forwarding. Since this is a dynamically-selected port, it is likely easiest if you open VirtualBox, and add a network forwarding rule from `127.0.0.1` on some port you know (e.g., `8000`) to `127.0.0.1` on whatever port is displayed in the output of the above command. - After starting VirtualBox, the VM that Vagrant started is visible: ![image](https://hackmd.io/_uploads/S1YpYYf1yl.png) - ... open the "Settings" (e.g., using the toolbar) when focused on that running VM. ![image](https://hackmd.io/_uploads/r10y9YG11g.png) - From there you can select the "Network" tab to display the network configuration. ![image](https://hackmd.io/_uploads/rySbcFM1Jx.png) - Unfold the "Advanced" controls ... ![image](https://hackmd.io/_uploads/SkIf5KzJJe.png) - ... and select the "Port Forwarding" button. From which you can add appropriate forwarding rules (note that you need to substitute your specific parameter values). ![image](https://hackmd.io/_uploads/Hkp89FGkye.png) - Remember that you need to click "OK" not only on the port forwarding configuration, but also to click "OK" on the underlying networking configuration window before port forwarding rules are applied. - You can then navigate in your web browser, to the address shown in the command output above, but ensure that the appropriate port number is substituted, i.e., the "Host Port" in your port forwarding rule. - You should see a fully-featured dashboard for your (cut-down) Kubernetes cluster. - ... although I have to admit that port forwarding didn't work when I tried it this year, so I used a different approach: running `vagrant ssh-config >ssh-conf` to write the OpenSSH configuration required to connect to the Vagrant VM into a temporary file, and then using SSH to forward a host local port to the guest local port, for me opened via opening another connection to the Vagrant VM with `ssh -F ssh-conf -L8080:localhost:32915 default`. - I clicked on the "Service" left menu: ![image](https://hackmd.io/_uploads/HyvURYGJke.png) - For example, by clicking on "Nodes" in the left-hand side menu, you can see the information that the `kubectl` command provided previously: ![image](https://hackmd.io/_uploads/rJIu0YzJkl.png) :::info :bulb: The dashboard is extremely powerful: do explore it, but for now we will proceed with a specific deployment exercise. ::: ### Deploying a Kubernetes service - The instructions that follow are adapted from https://kubernetes.io/docs/tutorials/hello-minikube/ - If you are leaving the dashboard running, you will need to open another terminal window and `vagrant ssh` into the VM running Minikube another time. - First create a deployment of the hello-node application. The command that follows confirms that the deployment has been fetched. ``` vagrant@vagrant:~$ minikube kubectl -- create deployment hello-minikube --image=gcr.io/kubernetes-e2e-test-images/echoserver:2.2 deployment.apps/hello-node created vagrant@vagrant:~$ minikube kubectl -- get deployments NAME READY UP-TO-DATE AVAILABLE AGE hello-minikube 1/1 1 1 118s ``` - Looking at the pods may show that the hello-node is still being created, so you can try again until the pod is running. ``` vagrant@vagrant:~$ minikube kubectl -- get pods NAME READY STATUS RESTARTS AGE hello-minikube-c4b877759-q7r4t 1/1 Running 0 13s ``` - You can get a list of recent events: ``` vagrant@vagrant:~$ minikube kubectl -- get events LAST SEEN TYPE REASON OBJECT MESSAGE 2m47s Normal Scheduled pod/hello-minikube-c4b877759-q7r4t Successfully assigned default/hello-minikube-c4b877759-q7r4t to minikube 2m46s Normal Pulling pod/hello-minikube-c4b877759-q7r4t Pulling image "gcr.io/kubernetes-e2e-test-images/echoserver:2.2" 2m37s Normal Pulled pod/hello-minikube-c4b877759-q7r4t Successfully pulled image "gcr.io/kubernetes-e2e-test-images/echoserver:2.2" in 9.618s (9.618s including waiting). Image size: 21692741 bytes. 2m37s Normal Created pod/hello-minikube-c4b877759-q7r4t Created container echoserver 2m37s Normal Started pod/hello-minikube-c4b877759-q7r4t Started container echoserver 2m47s Normal SuccessfulCreate replicaset/hello-minikube-c4b877759 Created pod: hello-minikube-c4b877759-q7r4t 2m47s Normal ScalingReplicaSet deployment/hello-minikube Scaled up replica set hello-minikube-c4b877759 to 1 40m Normal Starting node/minikube Starting kubelet. 40m Normal NodeAllocatableEnforced node/minikube Updated Node Allocatable limit across pods 40m Normal NodeHasSufficientMemory node/minikube Node minikube status is now: NodeHasSufficientMemory 40m Normal NodeHasNoDiskPressure node/minikube Node minikube status is now: NodeHasNoDiskPressure 40m Normal NodeHasSufficientPID node/minikube Node minikube status is now: NodeHasSufficientPID 39m Normal RegisteredNode node/minikube Node minikube event: Registered Node minikube in Controller 39m Normal Starting node/minikube ``` - Just running the containers is not enough to make the service available though. An invocation of the `expose` function of `kubectl` is required. ``` vagrant@vagrant:~$ minikube kubectl -- expose deployment hello-minikube --type=LoadBalancer --port=8080 service/hello-minikube exposed ``` - Listing the services will now confirm your hello-node service is present. ``` vagrant@vagrant:~$ minikube kubectl -- get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-minikube LoadBalancer 10.104.38.100 <pending> 8080:31833/TCP 29s kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 43m ``` - Let's try to connect to the `hello-node`. Although the following command won't show the service, it will tell you where you want to point your host machine's web browser. ``` vagrant@vagrant:~$ minikube service hello-minikube |-----------|----------------|-------------|---------------------------| | NAMESPACE | NAME | TARGET PORT | URL | |-----------|----------------|-------------|---------------------------| | default | hello-minikube | 8080 | http://192.168.49.2:31833 | |-----------|----------------|-------------|---------------------------| 🎉 Opening service default/hello-minikube in default browser... 👉 http://192.168.49.2:31833 ``` - You can set up port forwarding using VirtualBox in the same manner as above, and navigate your host computer's browser to a port that you have set up to reach the guest's IP and port number as shown in the output above. - However, the service itself may not be ready: you can use the commands above to list services and events to get an idea of what the application deployment is up to. - Eventually, you will be able to reach the test page: ![image](https://hackmd.io/_uploads/rJf6zqfykl.png) ### A stateless application using a deployment - Now, without caring so much about the actual functionality of the containers being orchestrated, let's explore the power of the orchestration itself. - This material is adapted from https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/ - Examine https://raw.githubusercontent.com/kubernetes/website/master/content/en/examples/application/deployment.yaml - Deploy this application from the YAML description: ``` vagrant@vagrant:~$ minikube kubectl -- apply -f https://k8s.io/examples/application/deployment.yaml deployment.apps/nginx-deployment created ``` - The output from this command has indicated the name of the deployment, i.e., `nginx-deployment`. - You can use the `describe` function to find out more information: ``` vagrant@vagrant:~$ minikube kubectl -- describe deployment nginx-deployment Name: nginx-deployment Namespace: default CreationTimestamp: Tue, 08 Oct 2024 11:09:48 +0000 Labels: <none> Annotations: deployment.kubernetes.io/revision: 1 Selector: app=nginx Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.14.2 Port: 80/TCP Host Port: 0/TCP Environment: <none> Mounts: <none> Volumes: <none> Node-Selectors: <none> Tolerations: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: nginx-deployment-d556bf558 (2/2 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 35s deployment-controller Scaled up replica set nginx-deployment-d556bf558 to 2 ``` - Note the mention of a ScalingReplicaSet. The contents of that set can be viewed using the following command, indicating that it's just a pair of replicas. ``` vagrant@vagrant:~$ minikube kubectl -- get pods -l app=nginx NAME READY STATUS RESTARTS AGE nginx-deployment-d556bf558-jkggb 1/1 Running 0 80s nginx-deployment-d556bf558-wzmc9 1/1 Running 0 80s ``` - If the status column does not show "Running" for all pods, then wait until all pods are "Running". - An updated version of the same deployment is available that steps the nginx version from 1.7.9 to 1.8 at: https://raw.githubusercontent.com/kubernetes/website/master/content/en/examples/application/deployment-update.yaml - Apply this deployment, and watch how your pods change: ``` kubectl apply -f https://k8s.io/examples/application/deployment-update.yaml ;\ while true; do sleep 0.5; kubectl get pods -l app=nginx; done ``` - You will need to press <kbd>control</kbd><kbd>c</kbd> to stop this command. Here's an example of edited output: ``` vagrant@vagrant:~$ minikube kubectl -- apply -f https://k8s.io/examples/application/deployment-update.yaml ;\ while true; do sleep 0.5; minikube kubectl -- get pods -l app=nginx; done deployment.apps/nginx-deployment configured NAME READY STATUS RESTARTS AGE nginx-deployment-7dbfbc79cf-ngfhb 0/1 ContainerCreating 0 1s nginx-deployment-d556bf558-jkggb 1/1 Running 0 3m20s nginx-deployment-d556bf558-wzmc9 1/1 Running 0 3m20s ... NAME READY STATUS RESTARTS AGE nginx-deployment-7dbfbc79cf-jjw25 0/1 ContainerCreating 0 1s nginx-deployment-7dbfbc79cf-ngfhb 1/1 Running 0 13s nginx-deployment-d556bf558-jkggb 1/1 Terminating 0 3m32s nginx-deployment-d556bf558-wzmc9 1/1 Running 0 3m32s ... NAME READY STATUS RESTARTS AGE nginx-deployment-7dbfbc79cf-jjw25 0/1 ContainerCreating 0 2s nginx-deployment-7dbfbc79cf-ngfhb 1/1 Running 0 14s nginx-deployment-d556bf558-wzmc9 1/1 Running 0 3m33s ... NAME READY STATUS RESTARTS AGE nginx-deployment-7dbfbc79cf-jjw25 1/1 Running 0 2s nginx-deployment-7dbfbc79cf-ngfhb 1/1 Running 0 14s nginx-deployment-d556bf558-wzmc9 1/1 Running 0 3m33s NAME READY STATUS RESTARTS AGE nginx-deployment-7dbfbc79cf-jjw25 1/1 Running 0 3s nginx-deployment-7dbfbc79cf-ngfhb 1/1 Running 0 15s nginx-deployment-d556bf558-wzmc9 0/1 Completed 0 3m34s NAME READY STATUS RESTARTS AGE nginx-deployment-7dbfbc79cf-jjw25 1/1 Running 0 4s nginx-deployment-7dbfbc79cf-ngfhb 1/1 Running 0 16s ^C ``` - What you should see in the above, is that the new version of the deployment progressively replaced the containers from the old version of the deployment. This is exactly what is desirable, in order to upgrade or modify container-driven applications without causing service interruptions. ### Observe your work in the dashboard - The above commands have—unsurprisingly—had significant effect in the Kubernetes dashboard. - For example, selecting "Workloads" on the left-side menu shows all of the deployments, pods, etc. ![image](https://hackmd.io/_uploads/BJ8Nr5Myke.png) - (The following screen-shot is just content reached by scrolling down from content shown in the preceding screen-capture.) ![image](https://hackmd.io/_uploads/HJIUr5zyye.png) ### Further deployments :::success :pencil: Suggested exercise: - Using the dashboard or the command line, experiment with installing other Kubernetes deployments that you locate on the web. - You may want to continue with the cloud orchestration section below, and return to this exercise. ::: ### Cleaning up - When you are done with your experimentation, you can simply `vagrant destroy` the VM used to host Minikube, since there should be no problematic, persistent changes to your host computer's setup. ## Cloud orchestration - We will use a template to deploy the WordPress content management system on EC2 using AWS CloudFormation, which is Amazon's cloud orchestration tool. - From the AWS Console ... ![image](https://hackmd.io/_uploads/SkVuTMGJkl.png) - ... navigate to the CloudFormation console. ![image](https://hackmd.io/_uploads/Syhq6Mzk1g.png) - You might instead see a page showing a list of "stacks" (possibly an empty list). The term "stack" is in the sense of a deployed software stack. ![image](https://hackmd.io/_uploads/SJznTfMkkx.png) - In either case, click on "Create stack", suboption "With new resources (standard)", and select "Choose an existing template", and "Upload a template file". ![image](https://hackmd.io/_uploads/HyQNRMz11l.png) - Using your host's web browser download https://gist.githubusercontent.com/dme26/92913ce2c43d7ec0b700a98a7f0e61f2/raw/c40e9f7785ed82dcefecda8011a4e37d4f5dbf98/WordPress_Single_Instance.yaml to a local file. - Choose that file under the "Upload a template file" selector. - The template file will undergo some preliminary checks, and when they are complete, you can click the "View in Designer" button. ![image](https://hackmd.io/_uploads/rkHMZ7Mkkx.png) :::warning :warning: If we were to run the template, WordPress wouldn't actually work, as the latest version of WordPress requires a later version of PHP than gets installed. We will use the designer to fix this, although of course could have edited the template file before uploading it to AWS CloudFormation. ::: - The template file will undergo some preliminary checks, and when they are complete, you can click the "View in Designer" button. ![image](https://hackmd.io/_uploads/ByFMMQMy1e.png) - Select the "Template" tab instead of the canvas ![image](https://hackmd.io/_uploads/HkqOMQG1kl.png) - Navigate to around line 470, which indicates that `/var/www/html` should be created from `http://wordpress.org/latest.tar.gz`. - Downgrade this URL for the latest version of WordPress to version 5.1, using the URL: `https://wordpress.org/wordpress-5.1.2.tar.gz` (You would not downgrade production software without a good reason: it is likely that security vulnerabilities would be opened up, however in this case we are just using the service temporarily and for exploration, so there shouldn't be any problems caused.) ![image](https://hackmd.io/_uploads/ryV17XMkyl.png) - Click the "Create template" button in the top right: ![image](https://hackmd.io/_uploads/ryRmQmzkJe.png) - Confirm and continue back to CloudFormation. ![image](https://hackmd.io/_uploads/SJHIXmf1Je.png) - Click "Next". ![image](https://hackmd.io/_uploads/BydK-7zkyg.png) - On the "Specify stack details" page, give your Stack a name. - Fill out all of the other details that the template requires to be completed. Note that for parameters such as the database passwords, these are for you to control what gets deployed, so they can be any values that you will remember. ![image](https://hackmd.io/_uploads/By7M4Qf11l.png) - Scrolling down, you will see a "Next" button, which you should click when you have filled in all of the required form fields. - You will reach the "Configure stack options" page, but none of the defaults should need to be changed. ![image](https://hackmd.io/_uploads/rkhXEmMk1e.png) - So scrolling down you will again see a "Next" button that you should click. ![image](https://hackmd.io/_uploads/H1nNNmG1Jl.png) - You will reach the Review page for your CloudFormation Stack. ![image](https://hackmd.io/_uploads/rJ0SV7zJJl.png) - ... and again scrolling down, you should not need to change any of the parameters. - You can click the "Submit" button. ![image](https://hackmd.io/_uploads/B15UNmGJJe.png) - This will return you to the "Stack details" page, where you can watch the deployment begin. ![image](https://hackmd.io/_uploads/SkSvN7z1kg.png) - After an amount of time (it might be a short time, or might be longer: first time for me was really quick, second time was... not), more events will appear, until the page announces "CREATE_COMPLETE". - From looking at the template, you can see that some outputs are specified. ![image](https://hackmd.io/_uploads/rkLtS7MJJl.png) - Click on the "Outputs" tab (off the right edge of visible tabs in the screen capture here---scroll right from the "Events" tab) to see the outputs that were generated. (Your Stack will need to have completed its deployment for these Outputs to be available.) ![image](https://hackmd.io/_uploads/Hk95HXzy1x.png) - In particular, we see the URL of the webserver that has been provisioned and configured, as key "WebsiteURL". - Click on that link, and you should reach your EC2 instance's WordPress configuration page. ![image](https://hackmd.io/_uploads/SJGnB7zkyx.png) - Feel free to experiment with setting up and then using WordPress. - When you have interacted with WordPress to your satisfaction, return to the CloudFormation page and choose "Delete" for your WordPress Stack. ![image](https://hackmd.io/_uploads/HJV0B7f1yx.png) - After you confirm your request to "Delete stack" you will be returned to the "Stack details" page, where you can watch your resources being de-provisioned. ![image](https://hackmd.io/_uploads/SyGyU7Gy1l.png) - You should ensure that the Stacks count returns to what it was before you started (1 for me, possibly 0 for you?), so that you are not being charged for services that you are not using. ![image](https://hackmd.io/_uploads/HyaNIXfJ1g.png) :::success :pencil: Suggested exercise: - Experiment with deploying other CloudFormation templates. - Make sure that you delete the "stack" after you have installed it, however, or services that you orchestrate will continue to run. :::

Import from clipboard

Paste your markdown or webpage here...

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lose their connection.

Create a note from template

Create a note from template

Oops...
This template has been removed or transferred.
Upgrade
All
  • All
  • Team
No template.

Create a template

Upgrade

Delete template

Do you really want to delete this template?
Turn this template into a regular note and keep its content, versions, and comments.

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Forgot password

or

By clicking below, you agree to our terms of service.

Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
Wallet ( )
Connect another wallet

New to HackMD? Sign up

Help

  • English
  • 中文
  • Français
  • Deutsch
  • 日本語
  • Español
  • Català
  • Ελληνικά
  • Português
  • italiano
  • Türkçe
  • Русский
  • Nederlands
  • hrvatski jezik
  • język polski
  • Українська
  • हिन्दी
  • svenska
  • Esperanto
  • dansk

Documents

Help & Tutorial

How to use Book mode

Slide Example

API Docs

Edit in VSCode

Install browser extension

Contacts

Feedback

Discord

Send us email

Resources

Releases

Pricing

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions and GitHub Sync
Get Full History Access

  • Edit version name
  • Delete

revision author avatar     named on  

More Less

Note content is identical to the latest version.
Compare
    Choose a version
    No search result
    Version not found
Sign in to link this note to GitHub
Learn more
This note is not linked with GitHub
 

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitHub

      Please authorize HackMD on GitHub
      • Please sign in to GitHub and install the HackMD app on your GitHub repo.
      • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
      Learn more  Sign in to GitHub

      Push the note to GitHub Push to GitHub Pull a file from GitHub

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh Authorize more repos
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Include title and tags
      Available push count

      Pull from GitHub

       
      File from GitHub
      File from HackMD

      GitHub Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Danger Zone

      Unlink
      You will no longer receive notification when GitHub file changes after unlink.

      Syncing

      Push failed

      Push successfully