---
# System prepended metadata

title: Deploying your first K8s on AWS EKS
tags: [2020 12/07 THU Developer Associate Workshop]

---

---
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. Introducing the concept of K8s - https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/
2. What is k8s and what it could do? -https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/
3. Components of K8s -https://kubernetes.io/docs/concepts/overview/components/
4. Componernts of Pod - https://kubernetes.io/docs/concepts/overview/components/
5. 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**
```
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
```
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/
---
講師個人相關連結(歡迎加好友)
---
![](https://i.imgur.com/UJjgAbn.jpg)

Youtube: https://www.youtube.com/c/LCAWS/videos
Github: lawrencechen0921
Facebook: Lawrence Chen
Instagram: klunreal4show
