Kubernetesでcert-manager使ってみる。

#初めに
kube-lego 使おうとしたらcert-managerに置き換わるとのこと。
使い方忘れないようにメモ。

#目的
自サイトをHTTPSでアクセスできるようにする。
ドメイン例:sub.domain.xxx

#前提
自宅でKubernetes環境を構築
ingress構築済み

#参考URL

####HTTP検証を使用してACME証明書を発行する方法
https://cert-manager.readthedocs.io/en/latest/tutorials/acme/http-validation.html

#手順
##helmでcert-managerをインストール

```bash

$ helm install \
    --name https \
    --namespace kube-system \
    stable/cert-manager
```

確認はこんな感じで。my-nginxはingress。

```bash

$ helm ls
NAME            REVISION        UPDATED                         STATUS          CHART                   NAMESPACE
https           1               Wed Jun 20 19:30:25 2018        DEPLOYED        cert-manager-v0.3.2     kube-system　★
my-nginx        3               Sun Jun 17 16:31:42 2018        DEPLOYED        nginx-ingress-0.20.3    default


$ kubectl get pod -n kube-system
NAME                                  READY     STATUS    RESTARTS   AGE
cert-manager-https-df7dbbdb7-pkk56    1/1       Running   0          50s　★
```

##Let's EncryptへのHTTP検証を有効にするために必要な情報を入力
必要なものはメールアドレス。

```issuer.yaml
apiVersion: certmanager.k8s.io/v1alpha1
kind: Issuer
metadata:
  name: letsencrypt-staging　★issuerの名前を指定
  namespace: default
spec:
  acme:
    # The ACME server URL
#   server: https://acme-staging-v02.api.letsencrypt.org/directory
    server: https://acme-v02.api.letsencrypt.org/directory　<= 本番用。上の URL の場合はステージングとなるので注意。
    # Email address used for ACME registration
    email: XXXXXXXX@gmail.com ★ ここを編集
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-staging
    # Enable the HTTP-01 challenge provider
    http01: {}
```

###作成したissur.yamlを読み込ませる。

```bash

$ kubectl create -f issuer.yaml
```

###issuerを確認する。

```bash

$ kubectl describe issuer
Name:         letsencrypt-staging
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  certmanager.k8s.io/v1alpha1
Kind:         Issuer
Metadata:
  Cluster Name:
  Creation Timestamp:  2018-06-20T10:35:56Z
  Generation:          0
  Resource Version:    26900943
  Self Link:           /apis/certmanager.k8s.io/v1alpha1/namespaces/default/issuers/letsencrypt-staging
  UID:                 b6f14fec-7475-11e8-a286-xxxxxxxxxxxxxxxx
Spec:
  Acme:
    Email:  XXXXXXXX@gmail.com
    Http 01:
    Private Key Secret Ref:
      Key:
      Name:  letsencrypt-staging
    Server:  https://acme-v02.api.letsencrypt.org/directory
Status:
  Acme:
    Uri:  https://acme-v02.api.letsencrypt.org/acme/acct/xxxxxxxxxxx
  Conditions:
    Last Transition Time:  2018-06-20T10:35:57Z
    Message:               The ACME account was registered with the ACME server
    Reason:                ACMEAccountRegistered　★ 登録できていることを確認する
    Status:                True
    Type:                  Ready
Events:                    <none>
$ 
```


##証明書を発行するドメインを指定
必要なものはドメイン。
今回は例としてsub.domain.xxxを指定している。

```cert.yaml
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
  name: sub.domain.xxx
  namespace: default
spec:
  secretName: sub.domain.xxx-tls ★ここで指定したsecretが作成される
  issuerRef:
    name: letsencrypt-staging ★作成したissuerを指定
  commonName: sub.domain.xxx
  dnsNames:
  - sub.domain.xxx
  acme:
    config:
    - http01:
        ingressClass: nginx
      domains:
      - domain.xxx
    - http01:
        ingress: https ★ 後で作成するingressの名前を指定している。
      domains:
      - sub.domain.xxx
```

###作成したcert.yamlを読み込ませる。

```bash
$ kubectl create -f cert.yaml
```

###certificationを確認する。

```bash
$ kubectl describe cert
Name:         sub.domain.xxx
Namespace:    default
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"certmanager.k8s.io/v1alpha1","kind":"Certificate","metadata":{"annotations":{},"name":"sub.domain.xxx","namespace":"default"},"spec":...
API Version:  certmanager.k8s.io/v1alpha1
Kind:         Certificate
Metadata:
  Cluster Name:
  Creation Timestamp:  2018-06-20T11:13:32Z
  Generation:          0
  Resource Version:    26906184
  Self Link:           /apis/certmanager.k8s.io/v1alpha1/namespaces/default/certificates/sub.domain.xxx
  UID:                 f7c092fc-747a-11e8-a286-xxxxxxxxxxx
Spec:
  Acme:
    Config:
      Domains:
        domain.xxx
      Http 01:
        Ingress:
        Ingress Class:  nginx
      Domains:
        sub.domain.xxx
      Http 01:
        Ingress:  https
  Common Name:    sub.domain.xxx
  Dns Names:
    sub.domain.xxx
  Issuer Ref:
    Name:       letsencrypt-staging
  Secret Name:  sub-domain-xxx-tls
Status:
  Acme:
    Order:
      URL:  https://acme-v02.api.letsencrypt.org/acme/order/xxxxxxxxxx/xxxxxxxxxxxx
  Conditions:
    Last Transition Time:  2018-06-20T11:13:35Z
    Message:               Order validated
    Reason:                OrderValidated
    Status:                False
    Type:                  ValidateFailed ★ここは無視
    Last Transition Time:  <nil>
    Message:               Certificate issued successfully ★認証成功したっぽい
    Reason:                CertIssued
    Status:                True
    Type:                  Ready
Events:
  Type    Reason        Age   From          Message
  ----    ------        ----  ----          -------
  Normal  CreateOrder   57s   cert-manager  Created new ACME order, attempting validation...
  Normal  IssueCert     57s   cert-manager  Issuing certificate...
  Normal  CertObtained  55s   cert-manager  Obtained certificate from ACME server
  Normal  CertIssued    55s   cert-manager  Certificate issued successfully
$ 
```

###secretを確認する。
```bash
$ kubectl get secret
NAME                                 TYPE                                  DATA      AGE
sub-domain-xxx-tls                   kubernetes.io/tls                     2         6m
$ 
```



##ingressを作成
```https-url.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: https ★ ingressの名前をhttpsとする
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: 'true'
spec:
  rules:
    - host: sub.domain.xxx
      http:
        paths:
          - backend:
              serviceName: nginx-service　★ 予め用意しておいた Service を指定
              servicePort: 80
            path: /
  tls:
    - hosts:
        - "sub.domain.xxx"
      secretName: domain-xxx-tls
```

###作成したhttps-url.yamlを読み込ませる。

```bash
$ kubectl create -f https-url.yaml
```

###作成したingressを確認する。

```bash
$ kubectl get ingress
NAME      HOSTS                          ADDRESS   PORTS     AGE
https     sub.domain.xxx                           80, 443   1h
$ 
```



##証明書取得の進捗確認を行う。
kubectl get pod -n kube-system で確認したものを指定する。

```bash
$ kubectl logs -n kube-system cert-manager-https-df7dbbdb7-pkk56
～省略～
I0620 10:35:56.428437       1 controller.go:136] issuers controller: syncing item 'default/letsencrypt-staging'
I0620 10:35:56.428599       1 acme.go:159] getting private key (letsencrypt-staging->tls.key) for acme issuer default/letsencrypt-staging
I0620 10:35:56.430503       1 logger.go:67] Calling GetAccount
I0620 10:35:57.610297       1 setup.go:73] letsencrypt-staging: verified existing registration with ACME server
I0620 10:35:57.610389       1 helpers.go:69] Setting lastTransitionTime for Issuer "letsencrypt-staging" condition "Ready" to 2018-06-20 10:35:57.610344573 +0000 UTC m=+329.535941771
I0620 10:35:57.630181       1 controller.go:150] issuers controller: Finished processing work item "default/letsencrypt-staging"
I0620 10:35:57.638611       1 controller.go:136] issuers controller: syncing item 'default/letsencrypt-staging'
I0620 10:35:57.638796       1 acme.go:159] getting private key (letsencrypt-staging->tls.key) for acme issuer default/letsencrypt-staging
I0620 10:35:57.640483       1 logger.go:67] Calling GetAccount
I0620 10:35:58.722133       1 setup.go:73] letsencrypt-staging: verified existing registration with ACME server
I0620 10:35:58.740751       1 controller.go:150] issuers controller: Finished processing work item "default/letsencrypt-staging"
I0620 10:37:10.180367       1 controller.go:177] certificates controller: syncing item 'default/sub.domain.xxx'
I0620 10:37:10.182136       1 sync.go:177] Certificate default/sub.domain.xxx scheduled for renewal in 1438 hours
I0620 10:37:10.182333       1 controller.go:191] certificates controller: Finished processing work item "default/sub.domain.xxx"

```

#削除、再発行手順
以下、コマンドを実行する。

```bash
$ kubectl delete -f https-url.yaml
$ kubectl delete -f cert.yaml
$ kubectl delete -f issuer.yaml
$ kubectl delete secret sub-domain-xxx-tls
```