Akamai Cloud Computing ServiceのLKEでTLSを使用してNginxのIngress Controllerをセットアップする 

# はじめに

Akamai Cloud Computing ServiceのLinode Kubernetes Engine(LKE)を利用してサービスを外部に公開するためには、外部からの接続を受け付けるためのロードバランサーとTLS(HTTPS)の通信を実現させるための証明書のセットアップが不可欠です。
今回は、Nginxを利用し、Let's Encryptで証明書を発行する手順を紹介します。

構成としては、2つのサンプルのサービスを作成し、Nginx Ingress Controllerにて外部から接続を実現します。

<img alt="test.png" width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/6d15ce0d-7d81-f65f-c4c8-aac530936783.png" >

## Linode Kubernetes Engine(LKE) のクラスターを作成する

[Akamai Cloud Manager](https://cloud.linode.com/)にログインし、Kubernetesのメニューからクラスターを作成します。

https://www.linode.com/docs/products/compute/kubernetes/get-started/

Kubernetesクラスターを作成したら、Kubeconfigをダウンロードします。

kubectlがインストールされている端末でkubeconfigを設定します。

```
export KUBECONFIG=./example-kubeconfig.yaml
```
## cert-managerを利用してLet's Encryptの証明書を発行する

Nginx Ingressに利用する証明書をcert managerを利用してLet's Encryptで発行します。
証明書の認証にはAkamai EdgeDNSを利用します。
EdgeDNSには対象のゾーンを作成しており、API Keyを発行している前提となります。

https://cert-manager.io/docs/installation/

cert-managerをインストールします。

```
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml
```

podが作成されていることを確認します。

```
kubectl get pods --namespace cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-6954d7bbbf-5dwc2              1/1     Running   0          72s
cert-manager-cainjector-84bdff4846-hnzhx   1/1     Running   0          73s
cert-manager-webhook-85b6b76d9b-chssc      1/1     Running   0          72s
```

下記を参考にcert managerの認証にEdge DNSを利用して設定を作成します。

https://cert-manager.io/docs/configuration/acme/dns01/akamai/

証明書を取得するためのyamlを記載します。
YAML内の以下の項目は適切なAPI情報に変更してください。

- `<Clinet Secret>`
- `<Access Token>`
- `<Clinet Token>`
- `<Hostname>`

```yaml:certificate.yaml
apiVersion: v1
kind: Secret
metadata:
  name: akamai-secret
type: Opaque
stringData:
  clientSecret:  <Client Secret>
  accessToken: <Access Token>
  clientToken: <Client Token>
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-akamai-issuer
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: example@gmail.com
    privateKeySecretRef:
      name: letsencrypt-acme-private-key
    solvers:
    - dns01:
        akamai:
          serviceConsumerDomain: <Hostname>
          clientTokenSecretRef:
            name: akamai-secret
            key: clientToken
          clientSecretSecretRef:
            name: akamai-secret
            key: clientSecret
          accessTokenSecretRef:
            name: akamai-secret
            key: accessToken
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: website-secret
spec:
  secretName: website-secret
  dnsNames:
  - 'shop.example.com'
  - 'blog.example.com'
  issuerRef:
    name: letsencrypt-akamai-issuer
    kind: Issuer
```

作成したyamlを適用します。

```
 kubectl create -f certificate.yaml
 ```

証明書の発行状況を確認します(Status: True)。

```
kubectl describe certificate website-certificate
```

証明書の発行が完了したことを確認します。

```
kubectl get certificate
NAME                  READY   SECRET           AGE
website-secret   True    website-secret   4m13s
```

## Nginxをセットアップする

下記を参考にNginxにてサンプルアプリケーションを2つ作成します。

https://www.linode.com/docs/guides/how-to-configure-load-balancing-with-tls-encryption-on-a-kubernetes-cluster/


```yaml:hello-one.yaml
apiVersion: v1
kind: Service
metadata:
  name: hello-two
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: hello-two
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-two
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-two
  template:
    metadata:
      labels:
        app: hello-two
    spec:
      containers:
      - name: hello-ingress
        image: nginxdemos/hello
        ports:
        - containerPort: 80
```

```yaml:hello-two.yaml
apiVersion: v1
kind: Service
metadata:
  name: hello-two
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: hello-two
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-two
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-two
  template:
    metadata:
      labels:
        app: hello-two
    spec:
      containers:
      - name: hello-ingress
        image: nginxdemos/hello
        ports:
        - containerPort: 80
```

作成した設定を反映させます。

```
kubectl create -f hello-one.yaml
kubectl create -f hello-two.yaml
```

アプリケーションが作成されていることを確認します。

```
kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
hello-one    ClusterIP   10.128.99.57     <none>        80/TCP    25s
hello-two    ClusterIP   10.128.254.228   <none>        80/TCP    20s
kubernetes   ClusterIP   10.128.0.1       <none>        443/TCP   7m35s
```

## Nginx Ingress Controllerを作成する

Helmを利用してKubernetesのクラスターにNginx Ingress Controllerをセットアップします。
NGINX Ingress Controllerをインストールすると作成したアプリケーションへのトラフィックの負荷分散に使用できる Linode NodeBalancerを作成します。

リポジトリを追加し、Nginx Ingress Controllerをインストールします。

```
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx
```

サービスが作成されていることを確認します。

```
kubectl -n default get services -o wide ingress-nginx-controller
NAME                       TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)                      AGE    SELECTOR
ingress-nginx-controller   LoadBalancer   10.128.173.212   xxx.xxx.xxx.xxx   80:32764/TCP,443:32304/TCP   4m7s   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
```

External IPを控え、2つのDNSレコードを作成します。

```
shop.example.com A xxx.xxx.xxx.xxx
blog.example.com A xxx.xxx.xxx.xxx
```

Ingressの設定ファイルを作成します。

```yaml:hello-app-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-app-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-akamai-issuer"
spec:
  tls:
  - hosts:
    - blog.example.com
    - shop.example.com
    secretName: website-secret
  rules:
  - host: blog.example.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-one
            port:
              number: 80
  - host: shop.example.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-two
            port:
              number: 80
```

設定したファイルを適用します。

```
kubectl create -f hello-app-ingress.yaml
```

## アプリケーションにアクセスする

Webブラウザ経由で「shop.example.com」と「blog.example.com」にアクセスします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/3d53a66a-091b-ab3e-6048-ee537e38e768.png)

正常にNginxのページが表示できていることを確認します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/f5aafb31-adcb-af03-0ba8-c46ef9405237.png)

HTTPSにて接続した際の証明書の設定も正しいか確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/3cee374b-44a6-2b7a-058a-2c01afc09371.png)

以上で構築は完了です。

# まとめ
オープンソースのソリューションを組み合わせることで、より安価にそしてポータビリティのあるアプリケーションを構築することができます。
Akamai Cloud Computing ServicesのLinode Kubernetes Engine(LKE)では今回紹介したような様々なサービスをKubernetes上で提供できるようになります。


# 関連記事

アカマイ・テクノロジーズ合同会社はQiitaでAkamai Cloud Computing Services関連など開発者向けの記事を掲載しております。

https://qiita.com/xenbase/items/52e2956a64cedc772bd9