iT邦幫忙

2023 iThome 鐵人賽

DAY 17
0
Cloud Native

30 天學習 Pulumi:用各種程式語言控制雲端資源系列 第 17

[Day 17] 實戰練習(4) - 在 EKS 中部署應用程式

  • 分享至 

  • xImage
  •  

本篇文章將會接續前面文章,前面已經介紹如何部署 EKS Cluster,並設定 NodeGroup 執行 worker node。今天就要在 K8S 內執行應用程式。

安裝與使用 Kubernetes Provider

安裝 Provider

今天會用到 Kubernetes Provider,這是 Pulumi 用來控制 K8S 資源的 Provider。可以透過套件管理工具安裝 Provider。

$ npm install @pulumi/kubernetes

安裝好後,就可以 import provider。

import * as k8s from '@pulumi/kubernetes';

從 EKS Cluster 取得 kubeconfig 設定 Provider

與 AWS Provider 相同,K8S provider 預設會讀取 ~/kube/config 的資訊做為預設的 K8S Cluster,所有的操作都會在該 cluster 中進行。但在這個練習中,要使用 EKS Cluster 做為 Cluster。因此可以產生 kubeconfig ,並建立屬於這個 Cluster 的 Provider。

const k8sProvider = new k8s.Provider(`my-provider`, {
  kubeconfig: eksCluster.getKubeconfig(),
});

建立了 Provider 之後,就可以在 k8s resource 的 opts 參數中,設定 provider 參數,並傳入前面設定的 provider。

例如以下範例會建立一個 namespace,名字為 test-namespaces,並且使用 EKS Cluster 的 kubeconfig 所建立的 K8S Provider。

const ns = new k8s.core.v1.Namespace('project-namespace', {
  apiVersion: 'v1',
  kind: 'Namespace',
  metadata: {
    name: 'test-namespaces',
  }
}, {provider: k8sProvider});

建立 Sample Application

接著來建立一個 sample application,這邊參考的範例為 AWS 文件的範例應用程式

建立 Component Resource

首先,建立 Component Resource 類別,與之前的練習一樣,將整個 Application 包裝成一個 Component Resource。

這邊簡單的讓 user 傳入 kubeconfig 就行,其他的資訊先寫死在類別中,有需要再變成參數讓使用者可以變更。

interface K8SSampleAppArgs {
  kubeConfig: pulumi.Input<string>;
}

export class K8SSampleApp extends pulumi.ComponentResource {
  constructor(name: string, args: K8SSampleAppArgs, opts: pulumi.ComponentResourceOptions = {}) {
    super('pulumi-practice:k8s_sample_app:K8SSampleApp', name, args, opts);
  }
}

1. 建立 Provider

接著在建構子中,直接建立 Provider,之後所有的 K8S 資源都會使用這個 Provider。

this.provider = new k8s.Provider(`${name}-provider`, {
  kubeconfig: args.kubeConfig,
});

2. 建立應用程式專用的 Namespace

Pulumi 的 kubernetes Provider 的使用方式與直接寫 YAML 的結構差不多,只是將 YAML 改成類似 JSON 的樣子來撰寫 (説類似 JSON 是因為在這是使用 JavaScript Object,差別在於 JS 的 Object 寫起來比 JSON 自由度高一點,key 不需要加引號)。不過用 Pulumi 撰寫有個好處 -- 可以讓 IDE 提供 Code Completion (程式碼自動補完)、 Typing Hint (型別提示)。

在使用時,可以根據所要用的 K8S api 去找到要使用的資源類別位置。如果 apiVersion 為 v1,則 apiVersion v1 的資源都會在 k8s.core.v1 之下。

另外像是 Deployment 的 apiVersion 為 apps/v1,則我們可以在 k8s.apps.v1 中找到 Deployment。依此類推,如果要用 Ingress,就到 k8s.networking.v1 中去找到 Ingress。

const ns = new k8s.core.v1.Namespace('project-namespace', {
  apiVersion: 'v1',
  kind: 'Namespace',
  metadata: {
    name: 'project-namespace',
  }
}, {provider: this.provider});

3. 建立 Deployment

接著來建立 Deployment,在這我們也可以善用程式語言的功能,將重複設定的值抽成變數。這就會比去寫 Helm Chart 的 Template 還方便。

const label = {
  app: 'eks-sample-linux',
};

const sampleApp = new k8s.apps.v1.Deployment('eks-sample-linux-deployment', {
  apiVersion: 'apps/v1',
  kind: 'Deployment',
  metadata: {
    name: 'eks-sample-linux-deployment',
    namespace: ns.metadata.name,
    labels: label
  },
  spec: {
    replicas: 3,
    selector: {
      matchLabels: label
    },
    template: {
      metadata: {
        labels: label
      },
      spec: {
        nodeSelector: {
          'kubernetes.io/os': 'linux',
        },
        affinity: {
          nodeAffinity: {
            requiredDuringSchedulingIgnoredDuringExecution: {
              nodeSelectorTerms: [
                {
                  matchExpressions: [
                    {
                      key: 'kubernetes.io/arch',
                      operator: 'In',
                      values: ['amd64', 'arm64']
                    }
                  ]
                }
              ]
            }
          }
        },
        containers: [
          {
            name: 'nginx',
            image: 'public.ecr.aws/nginx/nginx:1.23',
            ports: [
              {
                name: 'http',
                containerPort: 80,
              }
            ],
            imagePullPolicy: 'ifNotPresent',
          }
        ]
      },
    }
  }
}, {
  provider: this.provider,
  dependsOn: [ns],
  parent: ns,
});

4. 建立 Service

最後來建立 Service 並使用 LoadBalancer Type,讓 EKS 自動建立 Load Balancer。

const svc = new k8s.core.v1.Service('eks-sample-linux-service', {
  apiVersion: 'v1',
  kind: 'Service',
  metadata: {
    name: 'eks-sample-linux-service',
    namespace: ns.metadata.name,
    labels: {
      app: 'eks-sample-linux',
    }
  },
  spec: {
    type: 'LoadBalancer',
    selector: {
      app: 'eks-sample-linux',
    }
  }
}, {
  provider: this.provider,
  dependsOn: [sampleApp],
  parent: ns,
});

小節

今天的練習為部署簡單的 K8S Application,可以從練習中學習,如何在使用完 aws provider 後,又使用 k8s provider 操作其他種類的資源。學會操作簡單的資源後,就可以嘗試將既有的 Helm Chart 或是 kustomize 轉換為 pulumi 的 Component Resource。


上一篇
[Day 16] 實戰練習 (3) - 建立 EKS Cluster
下一篇
[Day 18] Pulumi 的 State 管理
系列文
30 天學習 Pulumi:用各種程式語言控制雲端資源30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言