--- tags: 2020 12/07 THU Developer Associate Workshop --- # Deploying your first K8s on AWS EKS Created by Lawrence Chen ![](https://i.imgur.com/QeCQT6u.jpg) 日期:December 07, 2020 時間: 8:30am-16:30pm 地點:東海大學管理學院M014 現場資訊 --- Telegram現場群: https://t.me/joinchat/N83WXhn8i_V9_uUUNaO8ZQ ![](https://i.imgur.com/vMXtYkj.png) --- Agenda --- **Event Warm Up Video** <iframe width="560" height="315" src="https://www.youtube.com/embed/y3ob_lWTVuo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> ___ 8:30 - 10:30 容器與Kubernetes基礎介紹 --- 1.The History of K8s- https://blog.risingstack.com/the-history-of-kubernetes/ 2. Introducing the concept of K8s - https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/ 3. What is k8s and what it could do? -https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/ 4. Components of K8s -https://kubernetes.io/docs/concepts/overview/components/ 5. Componernts of Pod - https://kubernetes.io/docs/concepts/overview/components/ 6. Architecture of K8s - https://www.eksworkshop.com/010_introduction/architecture/architecture_control_and_data_overview/ 10:30 - 12 :30 環境建立 --- 如果第一次使用Cloud9,可以參考下面這部影片介紹: <iframe width="560" height="315" src="https://www.youtube.com/embed/e6b3TQ7_CHg" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> - [x] 請確認你的AWS CLI正確執行 請確認以下指令: ``` 1. | aws sts get-caller-identity ``` 能正確返回結果,如果無法返回結果,使用 ``` 2.| aws configure --profile default ``` 來配置你的AWS CLI default profile --- **Install Kubernetes Tools** -- **1. Install Kubectl** **(地區幫我選us-west-2(Oregon))** ``` sudo curl --silent --location -o /usr/local/bin/kubectl \ https://amazon-eks.s3.us-west-2.amazonaws.com/1.17.11/2020-09-18/bin/linux/amd64/kubectl sudo chmod +x /usr/local/bin/kubectl ``` **2. Update awscli** Upgrade AWS CLI according to guidance in [AWS documentation](https://docs.aws.amazon.com/cli/latest/userguide/install-linux.html). ``` sudo pip install --upgrade awscli && hash -r ``` **3. Install jq, envsubst (from GNU gettext utilities) and bash-completion** ``` sudo yum -y install jq gettext bash-completion moreutils ``` **4. Install yq for yaml processing** ``` echo 'yq() { docker run --rm -i -v "${PWD}":/workdir mikefarah/yq yq "$@" }' | tee -a ~/.bashrc && source ~/.bashrc ``` **5. Verify the binaries are in the path and executable** ``` for command in kubectl jq envsubst aws do which $command &>/dev/null && echo "$command in path" || echo "$command NOT FOUND" done ``` **6. Enable kubectl bash_completion** ``` kubectl completion bash >> ~/.bash_completion . /etc/profile.d/bash_completion.sh . ~/.bash_completion ``` **7. set the AWS Load Balancer Controller version** ``` echo 'export LBC_VERSION="v2.0.0"' >> ~/.bash_profile . ~/.bash_profile ``` --- Create an IAM ROLE For Your Workspace --- 1. Follow [this deep link to create an IAM role with Administrator access](https://console.aws.amazon.com/iam/home#/roles$new?step=review&commonUseCase=EC2%2BEC2&selectedUseCase=EC2&policies=arn:aws:iam::aws:policy%2FAdministratorAccess). 2. Confirm that **AWS service** and **EC2** are selected, then click **Next:Permissions** to view permissions. 3. Confirm that **AdministratorAccess** is checked, then click **Next:Tags** to assign tags. 4. Take the defaults, and click **Next:Review** to review. 5. Enter **eksworkshop-admin** for the Name, and click **Create role**. ![](https://i.imgur.com/xUJyrgt.png) --- Attach The IAM ROLE To Your Workspace --- 1. Click the grey circle button (in top right corner) and select **Manage EC2 Instance** ![](https://i.imgur.com/JhJi25A.png) 2. Select the instance, then choose **Actions / Security / Modify IAM Role** ![](https://i.imgur.com/274w8FJ.png) 3. Choose **eksworkshop-admin** from the **IAM Role** drop down, and select **Save** ![](https://i.imgur.com/9S72l8k.png) --- Update IAM Settings For Your Workspace --- ![](https://i.imgur.com/dFOpPxW.png) To ensure temporary credentials aren’t already in place we will also remove any existing credentials file: ``` rm -vf ${HOME}/.aws/credentials ``` We should configure our aws cli with our current region as default. ``` export ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account) export AWS_REGION=$(curl -s 169.254.169.254/latest/dynamic/instance-identity/document | jq -r '.region') ``` Check if AWS_REGION is set to desired region ``` test -n "$AWS_REGION" && echo AWS_REGION is "$AWS_REGION" || echo AWS_REGION is not set ``` Let’s save these into bash_profile ``` echo "export ACCOUNT_ID=${ACCOUNT_ID}" | tee -a ~/.bash_profile echo "export AWS_REGION=${AWS_REGION}" | tee -a ~/.bash_profile aws configure set default.region ${AWS_REGION} aws configure get default.region ``` **Validate the IAM role** Use the [GetCallerIdentity ](https://docs.aws.amazon.com/cli/latest/reference/sts/get-caller-identity.html)CLI command to validate that the Cloud9 IDE is using the correct IAM role. ``` aws sts get-caller-identity --query Arn | grep eksworkshop-admin -q && echo "IAM role valid" || echo "IAM role NOT valid" ``` --- **Clone The Service Repos** --- ``` cd ~/environment git clone https://github.com/brentley/ecsdemo-frontend.git git clone https://github.com/brentley/ecsdemo-nodejs.git git clone https://github.com/brentley/ecsdemo-crystal.git ``` --- Create An SSH KEY --- Please run this command to generate SSH Key in Cloud9. This key will be used on the worker node instances to allow ssh access if necessary. ``` ssh-keygen ``` Upload the public key to your EC2 region: ``` aws ec2 import-key-pair --key-name "eksworkshop" --public-key-material file://~/.ssh/id_rsa.pub ``` If you got an error similar to **An error occurred (InvalidKey.Format) when calling the ImportKeyPair operation: Key is not in valid OpenSSH public key format** then you can try this command instead: ``` aws ec2 import-key-pair --key-name "eksworkshop" --public-key-material fileb://~/.ssh/id_rsa.pub ``` --- Create An AWS KMS CUSTOM MANAGED KEY (CMK) --- Create a CMK for the EKS cluster to use when encrypting your Kubernetes secrets: ``` aws kms create-alias --alias-name alias/eksworkshop --target-key-id $(aws kms create-key --query KeyMetadata.Arn --output text) ``` Let’s retrieve the ARN of the CMK to input into the create cluster command. ``` export MASTER_ARN=$(aws kms describe-key --key-id alias/eksworkshop --query KeyMetadata.Arn --output text) ``` We set the MASTER_ARN environment variable to make it easier to refer to the KMS key later. Now, let’s save the MASTER_ARN environment variable into the bash_profile ``` echo "export MASTER_ARN=${MASTER_ARN}" | tee -a ~/.bash_profile ``` ---- 下午場 13:30-16:30 Hands on Lab --- **Warm-up Video** **2019 AWS Container Day** <iframe width="560" height="315" src="https://www.youtube.com/embed/_j8XkgacXZQ" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> Let's go to use eksctl to build up our first AWS EKS!! --- Lab 1 Create your first EKS cluster 13:30-14:00 --- Prerequisites --- For this module, we need to download the eksctl binary: ``` curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp sudo mv -v /tmp/eksctl /usr/local/bin ``` Confirm the eksctl command works: ``` eksctl version ``` Enable eksctl bash-completion: ``` eksctl completion bash >> ~/.bash_completion . /etc/profile.d/bash_completion.sh . ~/.bash_completion ``` --- Create an EKS cluster --- Create an eksctl deployment file (eksworkshop.yaml) use in creating your cluster using the following syntax: ``` cat << EOF > eksworkshop.yaml --- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: eksworkshop-eksctl region: ${AWS_REGION} version: "1.17" availabilityZones: ["${AWS_REGION}a", "${AWS_REGION}b", "${AWS_REGION}c"] managedNodeGroups: - name: nodegroup desiredCapacity: 3 ssh: allow: true publicKeyName: eksworkshop # To enable all of the control plane logs, uncomment below: # cloudWatch: # clusterLogging: # enableTypes: ["*"] secretsEncryption: keyARN: ${MASTER_ARN} EOF ``` Next, use the file you created as the input for the eksctl cluster creation. ``` eksctl create cluster -f eksworkshop.yaml ``` --- TEST THE CLUSTER --- Confirm your nodes: ``` kubectl get nodes # if we see our 3 nodes, we know we have authenticated correctly ``` You could use this to check Cloudformation stack as well ``` eksctl utils describe-stacks --region=us-east-1 --cluster=eksworkshop-eksctl ``` Export the Worker Role Name for use throughout the workshop ``` STACK_NAME=$(eksctl get nodegroup --cluster eksworkshop-eksctl -o json | jq -r '.[].StackName') ROLE_NAME=$(aws cloudformation describe-stack-resources --stack-name $STACK_NAME | jq -r '.StackResources[] | select(.ResourceType=="AWS::IAM::Role") | .PhysicalResourceId') echo "export ROLE_NAME=${ROLE_NAME}" | tee -a ~/.bash_profile ``` You now have a fully working Amazon EKS Cluster that is ready to use! --- Lab 2 14:00-16:30 --- Deploying the example Microservices --- Make sure that your are in the environment directory, then we would use `cd` to change our directory to deploy our service. ``` cd ecsdemo-nodejs ``` The use `ll` to check **kubernetes** is out there. ``` cd kubernetes ``` Then check your *deployment.yaml* ``` apiVersion: apps/v1 kind: Deployment metadata: name: ecsdemo-nodejs labels: app: ecsdemo-nodejs namespace: default spec: replicas: 1 selector: matchLabels: app: ecsdemo-nodejs strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: labels: app: ecsdemo-nodejs spec: containers: - image: brentley/ecsdemo-nodejs:latest imagePullPolicy: Always name: ecsdemo-nodejs ports: - containerPort: 3000 protocol: TCP ``` In the sample file above, we describe the service and how it should be deployed. We will write this description to the kubernetes api using kubectl, and kubernetes will ensure our preferences are met as the application is deployed. The containers listen on port 3000, and native service discovery will be used to locate the running containers and communicate with them. --- DEPLOY NODEJS BACKEND API --- ![](https://i.imgur.com/zF6gh2x.png) Let’s bring up the NodeJS Backend API! Copy/Paste the following commands into your Cloud9 workspace: ``` cd ~/environment/ecsdemo-nodejs kubectl apply -f kubernetes/deployment.yaml kubectl apply -f kubernetes/service.yaml ``` We can watch the progress by looking at the deployment status: ``` kubectl get deployment ecsdemo-nodejs ``` --- DEPLOY CRYSTAL BACKEND API --- ![](https://i.imgur.com/ZtQbxUk.png) The same code we done before! ``` cd ~/environment/ecsdemo-crystal kubectl apply -f kubernetes/deployment.yaml kubectl apply -f kubernetes/service.yaml ``` We can watch the progress by looking at the deployment status: ``` kubectl get deployment ecsdemo-crystal ``` --- LET'S CHECK SERVICE TYPES --- Before we bring up the frontend service, let’s take a look at the service types we are using: This is kubernetes/service.yaml for our frontend service: ``` apiVersion: v1 kind: Service metadata: name: ecsdemo-frontend spec: selector: app: ecsdemo-frontend type: LoadBalancer ports: - protocol: TCP port: 80 targetPort: 3000 ``` Notice **type: LoadBalancer**: This will configure an ELB to handle incoming traffic to this service. Compare this to **kubernetes/service.yaml** for one of our backend services: ``` apiVersion: v1 kind: Service metadata: name: ecsdemo-nodejs spec: selector: app: ecsdemo-nodejs ports: - protocol: TCP port: 80 targetPort: 3000 ``` Notice there is no specific service type described. When we check the kubernetes documentation we find that the default type is ClusterIP. This Exposes the service on a cluster-internal IP. Choosing this value makes the service only reachable from within the cluster. --- ENSURE THE ELB SERVICE ROLE EXISTS --- In AWS accounts that have never created a load balancer before, it’s possible that the service role for ELB might not exist yet. We can check for the role, and create it if it’s missing. Copy/Paste the following commands into your Cloud9 workspace: ``` aws iam get-role --role-name "AWSServiceRoleForElasticLoadBalancing" || aws iam create-service-linked-role --aws-service-name "elasticloadbalancing.amazonaws.com" ``` --- DEPLOY FRONTEND SERVICE --- **Let’s bring up the Ruby Frontend!** ``` cd ~/environment/ecsdemo-frontend kubectl apply -f kubernetes/deployment.yaml kubectl apply -f kubernetes/service.yaml ``` We can watch the progress by looking at the deployment status: ``` kubectl get deployment ecsdemo-frontend ``` --- FIND THE SERVICE ADDRESS --- Now that we have a running service that is type: LoadBalancer we need to find the ELB’s address. We can do this by using the get services operation of kubectl: ``` kubectl get service ecsdemo-frontend ``` Notice the field isn’t wide enough to show the FQDN of the ELB. We can adjust the output format with this command: ``` kubectl get service ecsdemo-frontend -o wide ``` If we wanted to use the data programatically, we can also output via json. This is an example of how we might be able to make use of json output: ``` ELB=$(kubectl get service ecsdemo-frontend -o json | jq -r '.status.loadBalancer.ingress[].hostname') curl -m3 -v $ELB ``` > It will take several minutes for the ELB to become healthy and start passing traffic to the frontend pods. Then how to check our ELB domain? Use ``` echo $ELB ``` Then paste your ELB domain on your browser that you would see this! ![](https://i.imgur.com/SuMktg3.png) ---- SCALE THE BACKEND SERVICES --- When we launched our services, we only launched one container of each. We can confirm this by viewing the running pods: ``` kubectl get deployments ``` Now let’s scale up the backend services: ``` kubectl scale deployment ecsdemo-nodejs --replicas=3 kubectl scale deployment ecsdemo-crystal --replicas=3 ``` Confirm by looking at deployments again: ``` kubectl get deployments ``` Also, check the browser tab where we can see our application running. You should now see traffic flowing to multiple backend services. 你會看到奇蹟發生! --- SCALE THE FRONTEND --- Let’s also scale our frontend service! ``` kubectl get deployments kubectl scale deployment ecsdemo-frontend --replicas=3 kubectl get deployments ``` --- CLEANUP THE APPLICATIONS --- To delete the resources created by the applications, we should delete the application deployments: Undeploy the applications: ``` cd ~/environment/ecsdemo-frontend kubectl delete -f kubernetes/service.yaml kubectl delete -f kubernetes/deployment.yaml cd ~/environment/ecsdemo-crystal kubectl delete -f kubernetes/service.yaml kubectl delete -f kubernetes/deployment.yaml cd ~/environment/ecsdemo-nodejs kubectl delete -f kubernetes/service.yaml kubectl delete -f kubernetes/deployment.yaml ``` **更多EKSWorkshop請參考:** https://www.eksworkshop.com/ --- **New EKS feature on AWS re:Invent 2020** https://aws.amazon.com/tw/eks/eks-anywhere/?hp=r **Blog Support:** https://aws.amazon.com/blogs/containers/introducing-amazon-eks-add-ons/?sc_icampaign=amazon-eks-add-ons_reinvent20&sc_ichannel=ha&sc_icontent=awssm-5956&sc_iplace=ribbon&trk=ha_awssm-5956 --- **Other Tools- CDK8s** https://github.com/awslabs/cdk8s --- <html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><title>Kubectl for docker User</title><style> /* webkit printing magic: print all background colors */ html { -webkit-print-color-adjust: exact; } * { box-sizing: border-box; -webkit-print-color-adjust: exact; } html, body { margin: 0; padding: 0; } @media only screen { body { margin: 2em auto; max-width: 900px; color: rgb(55, 53, 47); } } body { line-height: 1.5; white-space: pre-wrap; } a, a.visited { color: inherit; text-decoration: underline; } .pdf-relative-link-path { font-size: 80%; color: #444; } h1, h2, h3 { letter-spacing: -0.01em; line-height: 1.2; font-weight: 600; margin-bottom: 0; } .page-title { font-size: 2.5rem; font-weight: 700; margin-top: 0; margin-bottom: 0.75em; } h1 { font-size: 1.875rem; margin-top: 1.875rem; } h2 { font-size: 1.5rem; margin-top: 1.5rem; } h3 { font-size: 1.25rem; margin-top: 1.25rem; } .source { border: 1px solid #ddd; border-radius: 3px; padding: 1.5em; word-break: break-all; } .callout { border-radius: 3px; padding: 1rem; } figure { margin: 1.25em 0; page-break-inside: avoid; } figcaption { opacity: 0.5; font-size: 85%; margin-top: 0.5em; } mark { background-color: transparent; } .indented { padding-left: 1.5em; } hr { background: transparent; display: block; width: 100%; height: 1px; visibility: visible; border: none; border-bottom: 1px solid rgba(55, 53, 47, 0.09); } img { max-width: 100%; } @media only print { img { max-height: 100vh; object-fit: contain; } } @page { margin: 1in; } .collection-content { font-size: 0.875rem; } .column-list { display: flex; justify-content: space-between; } .column { padding: 0 1em; } .column:first-child { padding-left: 0; } .column:last-child { padding-right: 0; } .table_of_contents-item { display: block; font-size: 0.875rem; line-height: 1.3; padding: 0.125rem; } .table_of_contents-indent-1 { margin-left: 1.5rem; } .table_of_contents-indent-2 { margin-left: 3rem; } .table_of_contents-indent-3 { margin-left: 4.5rem; } .table_of_contents-link { text-decoration: none; opacity: 0.7; border-bottom: 1px solid rgba(55, 53, 47, 0.18); } table, th, td { border: 1px solid rgba(55, 53, 47, 0.09); border-collapse: collapse; } table { border-left: none; border-right: none; } th, td { font-weight: normal; padding: 0.25em 0.5em; line-height: 1.5; min-height: 1.5em; text-align: left; } th { color: rgba(55, 53, 47, 0.6); } ol, ul { margin: 0; margin-block-start: 0.6em; margin-block-end: 0.6em; } li > ol:first-child, li > ul:first-child { margin-block-start: 0.6em; } ul > li { list-style: disc; } ul.to-do-list { text-indent: -1.7em; } ul.to-do-list > li { list-style: none; } .to-do-children-checked { text-decoration: line-through; opacity: 0.375; } ul.toggle > li { list-style: none; } ul { padding-inline-start: 1.7em; } ul > li { padding-left: 0.1em; } ol { padding-inline-start: 1.6em; } ol > li { padding-left: 0.2em; } .mono ol { padding-inline-start: 2em; } .mono ol > li { text-indent: -0.4em; } .toggle { padding-inline-start: 0em; list-style-type: none; } /* Indent toggle children */ .toggle > li > details { padding-left: 1.7em; } .toggle > li > details > summary { margin-left: -1.1em; } .selected-value { display: inline-block; padding: 0 0.5em; background: rgba(206, 205, 202, 0.5); border-radius: 3px; margin-right: 0.5em; margin-top: 0.3em; margin-bottom: 0.3em; white-space: nowrap; } .collection-title { display: inline-block; margin-right: 1em; } time { opacity: 0.5; } .icon { display: inline-block; max-width: 1.2em; max-height: 1.2em; text-decoration: none; vertical-align: text-bottom; margin-right: 0.5em; } img.icon { border-radius: 3px; } .user-icon { width: 1.5em; height: 1.5em; border-radius: 100%; margin-right: 0.5rem; } .user-icon-inner { font-size: 0.8em; } .text-icon { border: 1px solid #000; text-align: center; } .page-cover-image { display: block; object-fit: cover; width: 100%; height: 30vh; } .page-header-icon { font-size: 3rem; margin-bottom: 1rem; } .page-header-icon-with-cover { margin-top: -0.72em; margin-left: 0.07em; } .page-header-icon img { border-radius: 3px; } .link-to-page { margin: 1em 0; padding: 0; border: none; font-weight: 500; } p > .user { opacity: 0.5; } td > .user, td > time { white-space: nowrap; } input[type="checkbox"] { transform: scale(1.5); margin-right: 0.6em; vertical-align: middle; } p { margin-top: 0.5em; margin-bottom: 0.5em; } .image { border: none; margin: 1.5em 0; padding: 0; border-radius: 0; text-align: center; } .code, code { background: rgba(135, 131, 120, 0.15); border-radius: 3px; padding: 0.2em 0.4em; border-radius: 3px; font-size: 85%; tab-size: 2; } code { color: #eb5757; } .code { padding: 1.5em 1em; } .code-wrap { white-space: pre-wrap; word-break: break-all; } .code > code { background: none; padding: 0; font-size: 100%; color: inherit; } blockquote { font-size: 1.25em; margin: 1em 0; padding-left: 1em; border-left: 3px solid rgb(55, 53, 47); } .bookmark { text-decoration: none; max-height: 8em; padding: 0; display: flex; width: 100%; align-items: stretch; } .bookmark-title { font-size: 0.85em; overflow: hidden; text-overflow: ellipsis; height: 1.75em; white-space: nowrap; } .bookmark-text { display: flex; flex-direction: column; } .bookmark-info { flex: 4 1 180px; padding: 12px 14px 14px; display: flex; flex-direction: column; justify-content: space-between; } .bookmark-image { width: 33%; flex: 1 1 180px; display: block; position: relative; object-fit: cover; border-radius: 1px; } .bookmark-description { color: rgba(55, 53, 47, 0.6); font-size: 0.75em; overflow: hidden; max-height: 4.5em; word-break: break-word; } .bookmark-href { font-size: 0.75em; margin-top: 0.25em; } .sans { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, "Apple Color Emoji", Arial, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol"; } .code { font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; } .serif { font-family: Lyon-Text, Georgia, YuMincho, "Yu Mincho", "Hiragino Mincho ProN", "Hiragino Mincho Pro", "Songti TC", "Songti SC", "SimSun", "Nanum Myeongjo", NanumMyeongjo, Batang, serif; } .mono { font-family: iawriter-mono, Nitti, Menlo, Courier, monospace; } .pdf .sans { font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, "Apple Color Emoji", Arial, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol", 'Twemoji', 'Noto Color Emoji', 'Noto Sans CJK SC', 'Noto Sans CJK KR'; } .pdf .code { font-family: Source Code Pro, "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace, 'Twemoji', 'Noto Color Emoji', 'Noto Sans Mono CJK SC', 'Noto Sans Mono CJK KR'; } .pdf .serif { font-family: PT Serif, Lyon-Text, Georgia, YuMincho, "Yu Mincho", "Hiragino Mincho ProN", "Hiragino Mincho Pro", "Songti TC", "Songti SC", "SimSun", "Nanum Myeongjo", NanumMyeongjo, Batang, serif, 'Twemoji', 'Noto Color Emoji', 'Noto Sans CJK SC', 'Noto Sans CJK KR'; } .pdf .mono { font-family: PT Mono, iawriter-mono, Nitti, Menlo, Courier, monospace, 'Twemoji', 'Noto Color Emoji', 'Noto Sans Mono CJK SC', 'Noto Sans Mono CJK KR'; } .highlight-default { } .highlight-gray { color: rgb(155,154,151); } .highlight-brown { color: rgb(100,71,58); } .highlight-orange { color: rgb(217,115,13); } .highlight-yellow { color: rgb(223,171,1); } .highlight-teal { color: rgb(15,123,108); } .highlight-blue { color: rgb(11,110,153); } .highlight-purple { color: rgb(105,64,165); } .highlight-pink { color: rgb(173,26,114); } .highlight-red { color: rgb(224,62,62); } .highlight-gray_background { background: rgb(235,236,237); } .highlight-brown_background { background: rgb(233,229,227); } .highlight-orange_background { background: rgb(250,235,221); } .highlight-yellow_background { background: rgb(251,243,219); } .highlight-teal_background { background: rgb(221,237,234); } .highlight-blue_background { background: rgb(221,235,241); } .highlight-purple_background { background: rgb(234,228,242); } .highlight-pink_background { background: rgb(244,223,235); } .highlight-red_background { background: rgb(251,228,228); } .block-color-default { color: inherit; fill: inherit; } .block-color-gray { color: rgba(55, 53, 47, 0.6); fill: rgba(55, 53, 47, 0.6); } .block-color-brown { color: rgb(100,71,58); fill: rgb(100,71,58); } .block-color-orange { color: rgb(217,115,13); fill: rgb(217,115,13); } .block-color-yellow { color: rgb(223,171,1); fill: rgb(223,171,1); } .block-color-teal { color: rgb(15,123,108); fill: rgb(15,123,108); } .block-color-blue { color: rgb(11,110,153); fill: rgb(11,110,153); } .block-color-purple { color: rgb(105,64,165); fill: rgb(105,64,165); } .block-color-pink { color: rgb(173,26,114); fill: rgb(173,26,114); } .block-color-red { color: rgb(224,62,62); fill: rgb(224,62,62); } .block-color-gray_background { background: rgb(235,236,237); } .block-color-brown_background { background: rgb(233,229,227); } .block-color-orange_background { background: rgb(250,235,221); } .block-color-yellow_background { background: rgb(251,243,219); } .block-color-teal_background { background: rgb(221,237,234); } .block-color-blue_background { background: rgb(221,235,241); } .block-color-purple_background { background: rgb(234,228,242); } .block-color-pink_background { background: rgb(244,223,235); } .block-color-red_background { background: rgb(251,228,228); } .select-value-color-default { background-color: rgba(206,205,202,0.5); } .select-value-color-gray { background-color: rgba(155,154,151, 0.4); } .select-value-color-brown { background-color: rgba(140,46,0,0.2); } .select-value-color-orange { background-color: rgba(245,93,0,0.2); } .select-value-color-yellow { background-color: rgba(233,168,0,0.2); } .select-value-color-green { background-color: rgba(0,135,107,0.2); } .select-value-color-blue { background-color: rgba(0,120,223,0.2); } .select-value-color-purple { background-color: rgba(103,36,222,0.2); } .select-value-color-pink { background-color: rgba(221,0,129,0.2); } .select-value-color-red { background-color: rgba(255,0,26,0.2); } .checkbox { display: inline-flex; vertical-align: text-bottom; width: 16; height: 16; background-size: 16px; margin-left: 2px; margin-right: 5px; } .checkbox-on { background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%3Crect%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22%2358A9D7%22%2F%3E%0A%3Cpath%20d%3D%22M6.71429%2012.2852L14%204.9995L12.7143%203.71436L6.71429%209.71378L3.28571%206.2831L2%207.57092L6.71429%2012.2852Z%22%20fill%3D%22white%22%2F%3E%0A%3C%2Fsvg%3E"); } .checkbox-off { background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%3Crect%20x%3D%220.75%22%20y%3D%220.75%22%20width%3D%2214.5%22%20height%3D%2214.5%22%20fill%3D%22white%22%20stroke%3D%22%2336352F%22%20stroke-width%3D%221.5%22%2F%3E%0A%3C%2Fsvg%3E"); } </style></head><body><article id="babb89d6-9a12-48a5-a334-683cfebe4cb5" class="page sans"><header><div class="page-header-icon undefined"><img class="icon" src="Kubectl%20for%20docker%20User%20babb89d69a1248a5a334683cfebe4cb5/download.png"/></div><h1 class="page-title">Kubectl for docker User</h1></header><div class="page-body"><p id="1cd32b35-72d4-4dca-b1f5-05cd1465f76e" class="">在K8s與Docker上面的指令差異,如果你是第一次接觸到容器的概念建議你先摸熟Docker比較好銜接K8s概念,相關的文件官方網站都有,請你仔細閱讀。</p><div id="bd107221-aa82-40f8-8a47-a18671f55502" class="column-list"><div id="07f0db79-b6dd-4728-9c48-0e8b202f7d5b" style="width:50%" class="column"><p id="11a524b5-dcee-4e6b-b1d3-ecb02ea471dc" class="">你可以使用 <em>Kubectl </em>去與你的API server互動和聯繫,使用kubectl與docker line指令相似,但這邊會列舉一些差異給各位去品嚐。</p></div><div id="df21e142-27c1-47d3-94d5-015046ecd087" style="width:50%" class="column"><p id="5f194221-ad5f-4427-80cd-5749daa2e15b" class="">相關連結請點閱此: </p><figure id="f8543445-a337-4698-acfb-c4911baa7ad9"><a href="https://kubernetes.io/docs/reference/kubectl/docker-cli-to-kubectl/" class="bookmark source"><div class="bookmark-info"><div class="bookmark-text"><div class="bookmark-title">kubectl for Docker Users</div><div class="bookmark-description">You can use the Kubernetes command line tool kubectl to interact with the API Server. Using kubectl is straightforward if you are familiar with the Docker command line tool. However, there are a few differences between the docker commands and the kubectl commands. The following sections show a docker sub-command and describe the equivalent kubectl command.</div></div><div class="bookmark-href"><img src="https://kubernetes.io/images/favicon.png" class="icon bookmark-icon"/>https://kubernetes.io/docs/reference/kubectl/docker-cli-to-kubectl/</div></div><img src="https://kubernetes.io/images/kubernetes-horizontal-color.png" class="bookmark-image"/></a></figure></div></div><h1 id="04f5063c-3491-45a8-bc00-1a226150d1f0" class="">Docker run</h1><p id="84b5c654-d379-4f0a-a84c-621b12999e60" class="">要把nginx expose在deployment上,看看docker與Kubectl的差異。docker:</p><pre id="b286cb22-61b3-49fd-b6ef-18c44b2663a1" class="code"><code>docker run -d --restart=always -e DOMAIN=cluster --name nginx-app -p 80:80 nginx</code></pre><p id="0729d1d1-1f59-4a12-9e9d-f6d8c9c7dc18" class=""> </p><pre id="4d30538f-7472-4080-a104-ddacc9e75a38" class="code"><code>docker ps</code></pre><pre id="077bfbab-1f6f-42c4-9598-faf986752e57" class="code"><code>CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 55c103fa1296 nginx &quot;nginx -g &#x27;daemon of…&quot; 9 seconds ago Up 9 seconds 0.0.0.0:80-&gt;80/tcp nginx-app</code></pre><p id="fad93abc-8361-463b-abcd-8473b7791089" class=""> </p><p id="a0401d8a-c868-4e17-988e-0a13165403eb" class="">Kubectl:</p><p id="d92bbdc8-9c32-4ead-951c-338a6b00ae5b" class=""> </p><pre id="d3a457e9-91e1-4b1a-b5fc-d04213b89dd2" class="code"><code># start the pod running nginx kubectl create deployment --image=nginx nginx-app</code></pre><p id="682f457a-a1c9-40f2-b0a6-ac42df545f15" class=""> </p><pre id="99efdffc-8167-4a12-82e9-99d77b8aad31" class="code"><code># add env to nginx-app kubectl set env deployment/nginx-app DOMAIN=cluster</code></pre><p id="4e2d6a00-ca70-494e-9eae-f37af1ef42ac" class="">相關說明請看文件。</p></div></article></body></html> 講師個人相關連結(歡迎加好友) --- ![](https://i.imgur.com/UJjgAbn.jpg) Youtube: https://www.youtube.com/c/LCAWS/videos Github: lawrencechen0921 Facebook: Lawrence Chen Instagram: klunreal4show