Skip to content

Instantly share code, notes, and snippets.

@chusiang
Last active August 13, 2019 00:47
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chusiang/366ebcb5f9a14a6cb0c4e844cecfdc0e to your computer and use it in GitHub Desktop.
Save chusiang/366ebcb5f9a14a6cb0c4e844cecfdc0e to your computer and use it in GitHub Desktop.

[GDG Cloud KH Meetup #4]〈給 RD 的 Kubernetes 初體驗〉by William Yeh

tags: GDG-Cloud-KH, K8S

Info


前言

  • 今日的優惠碼,是給已沒有免費額度的人使用,若是新申請的使用者,會有 GCP 新用戶的免費額度可用。
  • Google Cloud 中文開發社群之 Telegram 群組聊天室 - https://t.me/googlecloudzhug
  • 請大家一張桌子至少坐兩個人,一旦 (學員) 自行練習過程中有問題時,還可向隔壁伙伴互面討論和 troubleshooting。

Agenda

  1. Containers
  2. Kubernetes
  3. Cloud (Use the Kubernetes in Cloud)

Goals

  1. Kubernetes promising trends (賣點在哪?)
  2. Adopt gradually
  3. Prepare mindset

Prepar the GKE on GCP for LAB # 6.0 & 7.0

因 GKE 需要點時間進行安裝,故在 LAB 1.0 之前,先至 GCP 進行 setup 的動作。

GKE Setup:

  1. Redeem Google Cloud coupon
  2. Create project in GCP
  3. Create GKE cluster

Redeem Google Cloud coupon

Please reference the workflow on paper.

  1. Go to https://cloud.google.com/redeem
  2. Key in the coupon and apply.

Create project in GCP / Create K8s-enabled Project

  1. Go to the "Kubernetes Engine".

    https://console.cloud.google.com/projectselector2/kubernetes

  2. 建立一個新專案 (或選取之前建立好的專案)。

    (Create one new project, or select created project.)

  3. 確定專案名稱是否是剛剛選取的名稱,此例為 My GKE Lab1

    (Make sure the project name. We use My GKE Lab1 project in this case.)

Create GKE cluster

  1. 啟動 Cloud Shell (1/2):點擊右上角的「終端機 (Terminal)」圖示。

    (Launch the Cloud Shell (1/2): Click the Terminal icon.)

  2. 啟動 Cloud Shell (2/2):點擊「啟動 CLOUD SHELL」的按鈕。

    (Launch the Cloud Shell (2/2): Click the Launch CLOUD SHELL button.)

  3. 取得 Project ID

    (Get the project ID.)

    my-gke-lab1

  4. Set the project via Project ID.

    $ gcloud config set project <PROJECT_ID>

    chusiang_lai@cloudshell:~ (my-gke-lab1)$ gcloud config set project my-gke-lab1
    Updated property [core/project].
    
  5. Set the region and zone.

    $ gcloud config set compute/zone us-west1-a

    chusiang_lai@cloudshell:~ (my-gke-lab1)$ gcloud config set compute/zone us-west1-a
    Updated property [compute/zone].
    
  6. Create K8s clusters.

    $ gcloud container clusters create k8s201908 --num-nodes 3

    chusiang_lai@cloudshell:~ (my-gke-lab1)$ gcloud container clusters create k8s201908 --num-nodes 3
    WARNING: In June 2019, node auto-upgrade will be enabled by default for newly created clusters and node pools. To disable it, use the `--no-enable-autoupgrade`
    flag.
    WARNING: Starting in 1.12, new clusters will have basic authentication disabled by default. Basic authentication can be enabled (or disabled) manually using the
     `--[no-]enable-basic-auth` flag.
    WARNING: Starting in 1.12, new clusters will not have a client certificate issued. You can manually enable (or disable) the issuance of the client certificate u
    sing the `--[no-]issue-client-certificate` flag.
    WARNING: Currently VPC-native is not the default mode during cluster creation. In the future, this will become the default mode and can be disabled using `--no-
    enable-ip-alias` flag. Use `--[no-]enable-ip-alias` flag to suppress this warning.
    WARNING: Starting in 1.12, default node pools in new clusters will have their legacy Compute Engine instance metadata endpoints disabled by default. To create a
     cluster with legacy instance metadata endpoints disabled in the default node pool, run `clusters create` with the flag `--metadata disable-legacy-endpoints=tru
    e`.
    WARNING: Your Pod address range (`--cluster-ipv4-cidr`) can accommodate at most 1008 node(s).
    This will enable the autorepair feature for nodes. Please see https://cloud.google.com/kubernetes-engine/docs/node-auto-repair for more information on node auto
    repairs.
    Creating cluster k8s201908 in us-west1-a... Cluster is being deployed...⠏
    

(Back to slides ...)

Prepar on local for LAB # 1.0 ~ 5.0

  1. Go to the https://github.com/William-Yeh/workshop-k8s201908 .

  2. Get the sample project via git clone.

    [ jonny@unicorn ~ ] - 14:40
    $ git clone https://github.com/William-Yeh/workshop-k8s201908.git
    
  3. Enter this project.

    [ jonny@unicorn ~ ] - 14:42
    $ cd workshop-k8s201908/
    

Lab # 1.0: Frontend & Backend

Changes:

  1. Get this sample code of C# and MVC from Microsoft.

Lab # 2.0: Dockerize

Changes:

  1. Add the Dockerfile file.

Lab # 3.0: Docker Compose

Containers Port
Frontend TodoFronted 30000
Backend TodoAPI 30080

Changes:

  1. Add the docker-compose.yml file.

Hands-on:

  1. Checkout to 3.0 tag.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 2.0)) - 14:48
    (cmd)$ git checkout 3.0
    Previous HEAD position was 89f2e7f 2.0: Dockerize the app with simple Dockerfile and docker-compose.yml.
    HEAD is now at f7dc3e4 3.0: Separate frontend and backend into 2 distinct containers.
    
  2. Review files.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 3.0)) - 14:48
    (ins)$ tree .
    .
    ├── LICENSE
    ├── README.md
    ├── TodoApi
    │   ├── Controllers
    │   │   └── TodoController.cs
    │   ├── Dockerfile
    │   ├── LICENSE
    │   ├── Models
    │   │   ├── TodoContext.cs
    │   │   └── TodoItem.cs
    │   ├── Program.cs
    │   ├── Startup.cs
    │   ├── TodoApi.csproj
    │   ├── appsettings.Development.json
    │   └── appsettings.json
    ├── TodoApi-original.zip
    ├── TodoFrontend
    │   ├── Dockerfile
    │   ├── index.html
    │   ├── jquery-3.3.1.min.js
    │   └── site.js
    └── docker-compose.yml
    
    4 directories, 18 files
    
  3. Run containers.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 3.0)) - 14:48
    (ins)$ docker-compose up -d
    Creating network "workshop-k8s201908_default" with the default driver
    Building todo-api
    Step 1/13 : FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
     ---> 3af77ac73731
    Step 2/13 : WORKDIR /app
     ---> Running in f430e0b20b52
    Removing intermediate container f430e0b20b52
     ---> 8b7149f6bdcd
    Step 3/13 : COPY *.csproj .
     ---> a349dbb180b8
    Step 4/13 : RUN  dotnet restore
     ---> Running in ada285379fba
      Restore completed in 3.65 sec for /app/TodoApi.csproj.
    Removing intermediate container ada285379fba
     ---> e638dde0c78d
    Step 5/13 : COPY . .
     ---> 832aa52eb047
    Step 6/13 : RUN  dotnet publish -o out
     ---> Running in 0541629e4e1d
    Microsoft (R) Build Engine version 16.2.32702+c4012a063 for .NET Core
    Copyright (C) Microsoft Corporation. All rights reserved.
    
      Restore completed in 61.12 ms for /app/TodoApi.csproj.
      TodoApi -> /app/bin/Debug/netcoreapp2.2/TodoApi.dll
      TodoApi -> /app/out/
    Removing intermediate container 0541629e4e1d
     ---> ea17fcdd991a
    Step 7/13 : FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime
     ---> 3ee0429b27ad
    Step 8/13 : LABEL maintainer="william.pjyeh@gmail.com"
     ---> Running in 4eaf3256b79f
    Removing intermediate container 4eaf3256b79f
     ---> b4a4070d93e4
    Step 9/13 : ENV ASPNETCORE_URLS http://+:80
     ---> Running in 19a4868bcb30
    Removing intermediate container 19a4868bcb30
     ---> 9a64e28f467f
    Step 10/13 : EXPOSE 80
     ---> Running in 5c3038f9097c
    Removing intermediate container 5c3038f9097c
     ---> 38331774d119
    Step 11/13 : WORKDIR /app
     ---> Running in 9e33aaeb1e01
    Removing intermediate container 9e33aaeb1e01
     ---> f0bb3fb67cc4
    Step 12/13 : COPY --from=build /app/out ./
     ---> 69a3362e64c2
    Step 13/13 : ENTRYPOINT ["dotnet", "TodoApi.dll"]
     ---> Running in 4fd7f7a5be59
    Removing intermediate container 4fd7f7a5be59
     ---> 6e5ddb8f2e3f
    Successfully built 6e5ddb8f2e3f
    Successfully tagged todoapi:3.0
    WARNING: Image for service todo-api was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
    Building todo
    Step 1/5 : FROM busybox:1.30
    1.30: Pulling from library/busybox
    53071b97a884: Pull complete
    Digest: sha256:4b6ad3a68d34da29bf7c8ccb5d355ba8b4babcad1f99798204e7abb43e54ee3d
    Status: Downloaded newer image for busybox:1.30
     ---> 64f5d945efcc
    Step 2/5 : WORKDIR /app
     ---> Running in 0ae754b31362
    Removing intermediate container 0ae754b31362
     ---> 169cf1e37654
    Step 3/5 : COPY . .
     ---> b3accd7b6ee3
    Step 4/5 : EXPOSE 80
     ---> Running in b67f2f80d0f3
    Removing intermediate container b67f2f80d0f3
     ---> fdb878c03886
    Step 5/5 : CMD ["busybox", "httpd", "-f", "-p", "80"]
     ---> Running in e901359151a3
    Removing intermediate container e901359151a3
     ---> 524f3da6f6df
    Successfully built 524f3da6f6df
    Successfully tagged todofrontend:3.0
    WARNING: Image for service todo was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
    Creating workshop-k8s201908_todo-api_1 ... done
    Creating workshop-k8s201908_todo_1     ... done
    
    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 3.0)) - 14:49
    (ins)$
    
  4. Review the website of http://localhost:30000 .

  5. Finish this Lab. Clean this workspace for next Lab.

    1. Stop containers.

      # Stop containers.
      [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 3.0)) - 14:54
      (ins)$ docker-compose stop
      Stopping workshop-k8s201908_todo_1     ... done
      Stopping workshop-k8s201908_todo-api_1 ... done
      
    2. Remove containers.

      [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 3.0)) - 14:54
      (ins)$ docker-compose rm -f
      Going to remove workshop-k8s201908_todo_1, workshop-k8s201908_todo-api_1
      Removing workshop-k8s201908_todo_1     ... done
      Removing workshop-k8s201908_todo-api_1 ... done
      

Lab # 3.0 Review

  1. Architecture
  2. Main tasks
  3. Diff
  4. Tricks
  5. Question

Lab # 4.0: Local Kubernetes

  1. Checkout to 4.0 tag.

    $ git checkout 4.0

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 3.0)) - 15:11
    (ins)$ git checkout 4.0
    Previous HEAD position was f7dc3e4 3.0: Separate frontend and backend into 2 distinct containers.
    HEAD is now at 3a3502b 4.0: Support Kubernetes (locally).
    
  2. Review log.

    $ git log

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:11
    (ins)$ git log
    ...
    
    commit 3a3502b1ab772c9d5618f7142266371887cae124 (HEAD, tag: 4.0)
    Author: William Yeh <william.pjyeh@gmail.com>
    Date:   Wed Jul 10 11:15:57 2019 +0800
    
        4.0: Support Kubernetes (locally).
    
    commit f7dc3e4f11af64d9ec5c7a3ad248b18ff9853cad (tag: 3.0)
    Author: William Yeh <william.pjyeh@gmail.com>
    Date:   Wed Jul 10 11:14:48 2019 +0800
    
        3.0: Separate frontend and backend into 2 distinct containers.
    
    commit 89f2e7f76760257854aab0b1a0248e9fedee5f39 (tag: 2.0)
    Author: William Yeh <william.pjyeh@gmail.com>
    Date:   Wed Jul 10 11:13:54 2019 +0800
    
        2.0: Dockerize the app with simple Dockerfile and docker-compose.yml.
    
    commit 64b77d3322668f21c64a5d387d7dd2a4b68ebd0e (tag: 1.0)
    Author: William Yeh <william.pjyeh@gmail.com>
    Date:   Wed Jul 10 11:12:29 2019 +0800
    
    :
    
  3. Review diff.

    $ git diff --stat HEAD~1 HEAD

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:13
    (ins)$ git diff --stat HEAD~1 HEAD
     README.md                     |  40 ++++++++++++++++---
     k8s-dashboard.md              |  38 ++++++++++++++++++
     k8s/kubernetes-dashboard.yaml | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     k8s/todoapi-service.yml       |  52 +++++++++++++++++++++++++
     k8s/todofrontend-service.yml  |  52 +++++++++++++++++++++++++
     5 files changed, 338 insertions(+), 6 deletions(-)
    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:13
    (ins)$
    
  4. Review the todofrontend-service.yml

    • Container: 將許多服務包進同一個容器中
    • Kubernetes 架構:
      • Service

      • Deployment

        奇數選舉策略:最少一定要有 3 個。

      • Pod: 把多個 containers 綁在同個 IP、主機上。常見的例子有:

        • Backend service + redis。
        • Nginx + uWSGI + ...
      • Container

    ---
    
    # 對應的版號。
    apiVersion: v1
    
    # 對應 K8s 的 Service 或 Deployment。
    kind: Service                               # => Service
    
    # 描述。
    metadata:
      name: todofrontend
      labels:
        app: todo
        tier: frontend
    
    # 真正的核心。
    spec:
      type: NodePort
      ports:
        - port: 80
          nodePort: 30000
      selector:
        app: todo
        tier: frontend
    
    ---
    apiVersion: apps/v1
    kind: Deployment                            # ==> Deployment
    metadata:
      name: todofrontend
      labels:
        app: todo
        tier: frontend
    
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: todo
          tier: frontend
      strategy:
        rollingUpdate:
          maxSurge: 1
          maxUnavailable: 1
        type: RollingUpdate
    
      template:   # pod definition              # ===> pod
        metadata:
          labels:
            app: todo
            tier: frontend
        spec:
          containers:                           # ====> container
            - name: todofrontend
              image: todofrontend:3.0
              imagePullPolicy: IfNotPresent
              ports:
                - containerPort: 80
          #dnsPolicy: ClusterFirst
          #restartPolicy: Always
    

Deployment & Replica

Replicas = 3

  1. Deployment 包含 Pod 和 container。
  2. Pod 包含 container。

Make sure you're using local Kubernetes

https://github.com/William-Yeh/workshop-k8s201908/tree/4.0

  1. kubectl config view

Hands-on of deploy to Kubernetes

  1. Create todo namespace.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:40
    (ins)$ kubectl create ns todo
    namespace/todo created
    
  2. Get namespace status.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:40
    (cmd)$ kubectl get ns
    NAME              STATUS   AGE
    default           Active   19m
    kube-node-lease   Active   20m
    kube-public       Active   20m
    kube-system       Active   20m
    todo              Active   36s
    

Build

[ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:41
(ins)$ docker-compose build
Building todo-api
Step 1/13 : FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
 ---> 3af77ac73731
Step 2/13 : WORKDIR /app
 ---> Running in 0dd4ba363418
Removing intermediate container 0dd4ba363418
 ---> a7e67b42ca56
Step 3/13 : COPY *.csproj .
 ---> 7dcba74980a0
Step 4/13 : RUN  dotnet restore
 ---> Running in fc08f13bae4c
  Restore completed in 996.91 ms for /app/TodoApi.csproj.
Removing intermediate container fc08f13bae4c
 ---> 121cf4a9687b
Step 5/13 : COPY . .
 ---> 78d96bf15d59
Step 6/13 : RUN  dotnet publish -o out
 ---> Running in 52a9ff3b903a
Microsoft (R) Build Engine version 16.2.32702+c4012a063 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 63.2 ms for /app/TodoApi.csproj.
  TodoApi -> /app/bin/Debug/netcoreapp2.2/TodoApi.dll
  TodoApi -> /app/out/
Removing intermediate container 52a9ff3b903a
 ---> 60b5a1d8b0e4
Step 7/13 : FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime
 ---> 3ee0429b27ad
Step 8/13 : LABEL maintainer="william.pjyeh@gmail.com"
 ---> Running in 215d38d42979
Removing intermediate container 215d38d42979
 ---> 0881e064ebd7
Step 9/13 : ENV ASPNETCORE_URLS http://+:80
 ---> Running in 16c32079f774
Removing intermediate container 16c32079f774
 ---> 4a488a38ad7a
Step 10/13 : EXPOSE 80
 ---> Running in 872944d628dc
Removing intermediate container 872944d628dc
 ---> 7a4504f487e4
Step 11/13 : WORKDIR /app
 ---> Running in 7d312d731af2
Removing intermediate container 7d312d731af2
 ---> 2a1ce265ad47
Step 12/13 : COPY --from=build /app/out ./
 ---> 60241e9eb65a
Step 13/13 : ENTRYPOINT ["dotnet", "TodoApi.dll"]
 ---> Running in 804aa3123794
Removing intermediate container 804aa3123794
 ---> e62cc653f93a
Successfully built e62cc653f93a
Successfully tagged todoapi:3.0
Building todo
Step 1/5 : FROM busybox:1.30
1.30: Pulling from library/busybox
53071b97a884: Pull complete
Digest: sha256:4b6ad3a68d34da29bf7c8ccb5d355ba8b4babcad1f99798204e7abb43e54ee3d
Status: Downloaded newer image for busybox:1.30
 ---> 64f5d945efcc
Step 2/5 : WORKDIR /app
 ---> Running in c09d9fb7e8ea
Removing intermediate container c09d9fb7e8ea
 ---> 11e21cf61811
Step 3/5 : COPY . .
 ---> e74c99765c36
Step 4/5 : EXPOSE 80
 ---> Running in 30041ed33d2c
Removing intermediate container 30041ed33d2c
 ---> 1af64117bba0
Step 5/5 : CMD ["busybox", "httpd", "-f", "-p", "80"]
 ---> Running in 7cf678322ccd
Removing intermediate container 7cf678322ccd
 ---> 2ae4f98e0e80
Successfully built 2ae4f98e0e80
Successfully tagged todofrontend:3.0
[ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:42
Review some status before run
  1. Review pods status of default pool.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:43
    (ins)$ kubectl get pods
    No resources found.
    
  2. Review pods status of todo pool.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:43
    (ins)$ kubectl get pods -n todo
    No resources found.
    
  3. Review deployment status of todo pool.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:44
    (cmd)$ kubectl get deploy -n todo
    No resources found.
    

(Option) Use minikube on macOS

  1. 因 macOS v10.14.6 的 Docker Desktop 無法正常執行 Kubernetes,故試著安裝 minikube。

    Kubernetes 與 minikube 入門教學 | TechBridge 技術共筆部落格

  2. 安裝完 minikube 之後,還得在 Termainal 手動啟用 Kubernetes clusters。

    [ jonny@unicorn ~ ] - 15:16
    (ins)$ minikube start
    😄  minikube v1.3.0 on Darwin 10.14.6
    💿  Downloading VM boot image ...
        minikube-v1.3.0.iso.sha256: 65 B / 65 B [=====================] 100.00% 0s
        minikube-v1.3.0.iso: 131.07 MiB / 131.07 MiB [==============] 100.00% 1m6s
    🔥  Creating virtualbox VM (CPUs=2, Memory=2000MB, Disk=20000MB) ...
    🐳  Preparing Kubernetes v1.15.2 on Docker 18.09.8 ...
    💾  Downloading kubelet v1.15.2
    💾  Downloading kubeadm v1.15.2
    🚜  Pulling images ...
    🚀  Launching Kubernetes ...
    ⌛  Waiting for: apiserver proxy etcd
    ...
    
  3. 待 minikube 的 Kubernetes clusters 跑起來後,Docker Desktop 的 Kubernetes 服務也恢復正常了。

    @chusiang: 咦?!反正它就是跑起來了,好在有跑起來,不然後面的 Kubernetes 本機 Lab 就開天窗了。🤣 感謝 @hashman 神救援!

  4. 如在 macOS 有安裝 minikube,記得在 Docker 的選單,把 Kubernetes 切回 docker-desktop 模式,不然得另行處理後面 Lab 的 port forwarding。

Run

Backend
  1. Apply todoapi-service to todo pool.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:42
    (ins)$ kubectl apply -f k8s/todoapi-service.yml -n todo
    service/todoapi created
    deployment.apps/todoapi created
    
  2. Review the ip mapping status of todo pool.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:45
    (ins)$ kubectl get svc -n todo
    NAME      TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
    todoapi   NodePort   10.101.6.95   <none>        80:30080/TCP   3m50s
    
  3. Review the deployment status of todo pool.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:49
    (ins)$ kubectl get deploy -n todo
    NAME      READY   UP-TO-DATE   AVAILABLE   AGE
    todoapi   0/3     3            0           5m47s
    
  4. Review the poods status of todo pool.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:50
    (ins)$ kubectl get pods -n todo
    NAME                       READY   STATUS             RESTARTS   AGE
    todoapi-7c5c486947-5tw6t   0/1     ImagePullBackOff   0          6m34s
    todoapi-7c5c486947-rz7h2   0/1     ErrImagePull       0          6m34s
    todoapi-7c5c486947-z5wgk   0/1     ImagePullBackOff   0          6m34s
    
  5. Try to delete one pod.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:50
    (ins)$ kubectl delete pods todoapi-7c5c486947-rz7h2 -n todo
    pod "todoapi-7c5c486947-rz7h2" deleted
    
  6. We can see the Kubernetes will auto launch the 3th pod after we removed.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:51
    (cmd)$ kubectl get pods -n todo
    NAME                       READY   STATUS             RESTARTS   AGE
    todoapi-7c5c486947-5tw6t   0/1     ImagePullBackOff   0          7m18s
    todoapi-7c5c486947-wz2tj   0/1     ErrImagePull       0          7s
    todoapi-7c5c486947-z5wgk   0/1     ImagePullBackOff   0          7m18s
    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:51
    (ins)$
    
Frontend
  1. Apply todofrontend-service to todo pool.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:51
    (ins)$ kubectl apply -f k8s/todofrontend-service.yml -n todo
    service/todofrontend created
    deployment.apps/todofrontend created
    
  2. Review the ip mapping status of todo pool.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 15:51
    (cmd)$ kubectl get svc -n todo
    NAME           TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
    todoapi        NodePort   10.101.6.95     <none>        80:30080/TCP   9m
    todofrontend   NodePort   10.99.135.208   <none>        80:30000/TCP   54s
    
  3. Try add new item via Frontend web (http://localhost:30000).

  4. Get api status via curl.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 16:10
    (cmd)$ curl http://localhost:30080/api/todo
    [{"id":1,"name":"Item1","isComplete":false}][ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 16:10
    (cmd)$ curl http://localhost:30080/api/todo   [{"id":1,"name":"Item1","isComplete":false}][ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 16:10
    (cmd)$ curl http://localhost:30080/api/todo
    [{"id":1,"name":"Item1","isComplete":false}][ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 16:10
    (cmd)$ curl http://localhost:30080/api/todo
    [{"id":1,"name":"Item1","isComplete":false}][ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 16:10
    (cmd)$ curl http://localhost:30080/api/todo
    [{"id":1,"name":"Item1","isComplete":false}][ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 16:10
    (ins)$
    

Lab # 3.0 Review

  1. Question:
    • We have not use share disk and memory, so the items data is not sync now.

Lab # 5.0: Local Kubernetes + refactor via environment variables

https://github.com/William-Yeh/workshop-k8s201908/tree/5.0

  1. Check to 5.0 tag.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 4.0)) - 16:15
    (cmd)$ git checkout 5.0
    Previous HEAD position was 3a3502b 4.0: Support Kubernetes (locally).
    HEAD is now at 47f84f0 5.0: Support ConfigMap and naming convention.
    
  2. Remove todo namespace of 4.0 Lab.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:15
    (ins)$ kubectl delete ns todo
    namespace "todo" deleted
    
  3. Review changes.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:19
    (ins)$ git diff --stat HEAD~1 HEAD
     README.md                    | 41 +++++++++++++++++++++++++++++++----------
     TodoFrontend/Dockerfile      | 11 ++++++++++-
     TodoFrontend/run.sh          | 16 ++++++++++++++++
     TodoFrontend/site.js         |  2 +-
     docker-compose.yml           |  2 +-
     k8s/config.local.yml         |  9 +++++++++
     k8s/todofrontend-service.yml | 14 ++++++++++++--
     7 files changed, 80 insertions(+), 15 deletions(-)
    

TodoFrontend 的部分將 Dockerfile 的 CMD 改為執行 run.sh 這個 shell script ,主要的目的為取代程式碼中的環境變數

  • Replace with sed: {{xxx}} -> $xxx

Preparation

  1. Create the todo namespace.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:19
    (ins)$ kubectl create ns todo
    namespace/todo created
    
  2. Apply config.local.yml to todo pool.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:25
    (ins)$ kubectl apply -f k8s/config.local.yml -n todo
    configmap/config.local created
    
  3. Review the config maps of todo pool.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:25
    (ins)$ kubectl get configmaps -n todo
    NAME           DATA   AGE
    config.local   3      37s
    

Build

Build new 5.0 image.

[ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 1
(ins)$ docker-compose build
Building todo-api
Step 1/13 : FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
 ---> 3af77ac73731
Step 2/13 : WORKDIR /app
 ---> Using cache
 ---> a7e67b42ca56
Step 3/13 : COPY *.csproj .
 ---> Using cache
 ---> 7dcba74980a0
Step 4/13 : RUN  dotnet restore
 ---> Using cache
 ---> 121cf4a9687b
Step 5/13 : COPY . .
 ---> Using cache
 ---> 78d96bf15d59
Step 6/13 : RUN  dotnet publish -o out
 ---> Using cache
 ---> 60b5a1d8b0e4
Step 7/13 : FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime
 ---> 3ee0429b27ad
Step 8/13 : LABEL maintainer="william.pjyeh@gmail.com"
 ---> Using cache
 ---> 0881e064ebd7
Step 9/13 : ENV ASPNETCORE_URLS http://+:80
 ---> Using cache
 ---> 4a488a38ad7a
Step 10/13 : EXPOSE 80
 ---> Using cache
 ---> 7a4504f487e4
Step 11/13 : WORKDIR /app
 ---> Using cache
 ---> 2a1ce265ad47
Step 12/13 : COPY --from=build /app/out ./
 ---> Using cache
 ---> 60241e9eb65a
Step 13/13 : ENTRYPOINT ["dotnet", "TodoApi.dll"]
 ---> Using cache
 ---> e62cc653f93a
Successfully built e62cc653f93a
Successfully tagged todoapi:3.0
Building todo
Step 1/8 : FROM busybox:1.30
 ---> 64f5d945efcc
Step 2/8 : WORKDIR /app
 ---> Using cache
 ---> 11e21cf61811
Step 3/8 : COPY . .
 ---> 98be11d67ac1
Step 4/8 : RUN chmod +x run.sh
 ---> Running in 85c55155993a
Removing intermediate container 85c55155993a
 ---> 8e7c83565fbb
Step 5/8 : ENV TODOAPI_HOST localhost
 ---> Running in b36f5fe1f734
Removing intermediate container b36f5fe1f734
 ---> 01d29407f4c6
Step 6/8 : ENV TODOAPI_PORT 30080
 ---> Running in 2386c465df0b
Removing intermediate container 2386c465df0b
 ---> 33b0c0a091ee
Step 7/8 : EXPOSE 80
 ---> Running in 7918de7a342d
Removing intermediate container 7918de7a342d
 ---> ceb4d9576c47
Step 8/8 : CMD ["./run.sh"]
 ---> Running in 9c0db2048fed
Removing intermediate container 9c0db2048fed
 ---> 8a51613c8863
Successfully built 8a51613c8863
Successfully tagged todofrontend:5.0
[ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:28
$

Run

  1. Apply todoapi-service to todo pool.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 1
    (cmd)$ kubectl apply -f k8s/todoapi-service.yml -n todo
    service/todoapi created
    deployment.apps/todoapi created
    
  2. Apply todofrontend-service to todo pool.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:30
    (ins)$ kubectl apply -f k8s/todofrontend-service.yml -n todo
    service/todofrontend created
    deployment.apps/todofrontend created
    
  3. Review the ip mapping status of todo pool.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:30
    (cmd)$ kubectl get svc -n todo
    NAME           TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
    todoapi        NodePort   10.111.165.42   <none>        80:30080/TCP   21s
    todofrontend   NodePort   10.111.152.45   <none>        80:30000/TCP   7s
    

EnvFrom

目的在於可以將 configMap 注入 env 設定。

https://github.com/William-Yeh/workshop-k8s201908/blob/5.0/k8s/todofrontend-service.yml#L51

    spec:
      containers:
        - name: todofrontend
          image: todofrontend:5.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
          envFrom:
            - configMapRef:
                name: config.local

LAB # 6.0: GKE

本 LAB 是手動選號 (ip address) 和自動選號都會實作到。

  1. Checkout to 6.0 tag.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 5.0)) - 16:32
    (cmd)$ git checkout 6.0
    Previous HEAD position was 47f84f0 5.0: Support ConfigMap and naming convention.
    HEAD is now at 0e7fd39 6.0: Support Kubernetes on the cloud (GKE for example) and use Skaffold to simplify the process.
    
  2. Diff.

    [ jonny@unicorn ~/workshop-k8s201908 ] ((HEAD detached at 6.0)) - 16:41
    (ins)$ git diff --stat HEAD~1 HEAD
     README.md                                | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
     docker-compose.yml                       |  23 -----------------
     gke-steps.md                             |  49 +++++++++++++++++++++++++++++++++++
     k8s/cloud/config.cloud.yml.tpl           |   9 +++++++
     k8s/cloud/fix-name.py                    |  93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     k8s/cloud/todoapi-service.yml.tpl        |  55 +++++++++++++++++++++++++++++++++++++++
     k8s/cloud/todofrontend-service.yml.tpl   |  65 ++++++++++++++++++++++++++++++++++++++++++++++
     k8s/{ => local}/config.local.yml         |   0
     k8s/{ => local}/todoapi-service.yml      |   5 ++--
     k8s/{ => local}/todofrontend-service.yml |   5 ++--
     skaffold.yaml                            |  35 +++++++++++++++++++++++++
     11 files changed, 405 insertions(+), 44 deletions(-)
    

Usage: the local case

https://github.com/William-Yeh/workshop-k8s201908/tree/6.0#usage-the-local-case

Please do this after class.

Usage: the cloud case

https://github.com/William-Yeh/workshop-k8s201908/tree/6.0#usage-the-cloud-case

  1. 回到 GCP 的 Cloud Shell 界面觀看 GKE Setup 的結果。

    承接「Prepar the GKE on GCP for LAB # 6.0 & 7.0」的 GKE Setup 步驟。

  2. 當看到 k8s201908 cluster 的狀態為 RUNNING 時,即代表 GKE 服務 Setup 成功,且正常執行!

  3. 講者小叮嚀:回頭記得砍掉課堂上已建好的環境,多練習幾次,才不白費本次拿到的 coupon!

Preparation

  1. Run the Workshop on GKE (Google Kubernetes Engine).

    https://github.com/William-Yeh/workshop-k8s201908/blob/6.0/gke-steps.md

  2. Allocate a static external IP address for TODOAPI_HOST:

    # reserve a new static external IP address for backend todoapi
    % gcloud compute addresses create todoapi --region=us-west1 --network-tier=PREMIUM
    
    # make sure the static external IP address has been allocated
    % gcloud compute addresses list
    

    Please remember 35.247.16.87 address of todoapi, because we will use it later.

  3. We will replace the ip address via TODOAPI_IP_ADDR variable.

    https://github.com/William-Yeh/workshop-k8s201908/blob/6.0/k8s/cloud/todoapi-service.yml.tpl#L11 .

    spec:
      type: LoadBalancer
      loadBalancerIP: TODOAPI_IP_ADDR  # external IP (ephemeral or static)
      ports:
        - name: http
          port: 80
          targetPort: 80
      selector:
        app: todo
        tier: backend
    
  4. 講者小叮嚀:回頭練習完,記得把靜態 (static) IP 拔掉,因為 static 種類的 VPC IP 是會收費的。

  5. Fill in correct image names and static IP addresses by modifying the PROJECT_ID and TODOAPI_IP_ADDR symbols in manifest files, by either:

    $ k8s/cloud/fix-name.py PROJECT_ID TODOAPI_IP_ADDR

    $ k8s/cloud/fix-name.py my-gke-lab1 35.247.16.87
    

  6. Create a todo namespace for this app: Create a todo namespace for this app: Load the ConfigMap content:

Build and Run

The Skaffold is like docker-compose for Kubernetes.

https://github.com/William-Yeh/workshop-k8s201908/blob/6.0/skaffold.yaml

  1. Use Skaffold to streamline the build-and-run process continuously:

    $ skaffold dev -p cloud --default-repo gcr.io/PROJECT_ID  -n todo
    
    # dev: Build-and-run with LiveReload mode, please don't use it on Production.
    # run: standard mode of one-shot build-and-run.
    

    若時間允許,可在 local 先體驗一下 Skaffold 的威力!再上 cloud 玩。

    (If we have more time, we can play Skaffold at local first, than cloud.)

  2. Review ip address.

    $ kubectl get svc -n todo
    

Q&A

  1. 課後想自行在本機繼續 Kubernetes,但它在本機運作上算穩定嗎?
    1. 使用 minikube project 會較穩定,但它相對需耗費較多的資源。
    2. docker-desktop 其實已可應付大多簡單的應用,而且也比較省資源。

LAB # 6.0 Review

  1. Architecture
  2. Main tasks
  3. ....

LAB # 7.0 Canary release

  1. 新的 K8s 會使用 Istio 來跑 Canary release,比傳統 K8s 方法來得簡單好用。
  2. 09/11 K8s Summit 有人會分享這部份,想聽的話,要記得去搶 workshop 的名額。

END

Remove GKE cluster

  1. Delete the todo namespace.

  2. Release the static ip address. (1/3)

  3. Release the static ip address. (2/3)

  4. Release the static ip address. (3/3)

  5. Delete the Kubernetes clusters.

  6. DONE (1/2).

  7. DONE (2/2).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment