2021年4月20日火曜日

Azure に Eclipse Che をTLS 有効・マルチユーザーモード・マルチノード・シングルホストでデプロイ

TLS 有効・マルチユーザーモード・マルチノード・シングルホストでデプロイ。

che-che.xxx.xxx.xxx.xxx.nip.io じゃなくて、 myide.xxx.xxx.xxx.xxx.nip.io でアクセスしたいので、シングルホストモードでやってみる。

前提条件

  • OS: Windows 10 Pro
  • Docker Desktop インストール済み
  • DNS に nip.io を利用
  • 自己証明書を使用
  • 3 ノードでデプロイ

作業用コンテナ起動

AKS 接続用の Docker コンテナを使う。

docker run -it --rm -v "$(pwd):/work" --workdir /work mikoto2000/aks-tools

Azure へログイン

az login

https://microsoft.com/devicelogin へアクセスして、表示されたコードを入力する。

Kubernetes クラスタ作成

### 必要な情報整理
RESOURCE_GROUP="eclipse-che"
AKS_NAME="eclipse-che"

az group create --name ${RESOURCE_GROUP} --location japaneast
az aks create --resource-group ${RESOURCE_GROUP} --name ${AKS_NAME} --node-vm-size Standard_DS2_v2 --node-count 3 --enable-addons monitoring --generate-ssh-keys

az aks get-credentials --name ${AKS_NAME} --resource-group ${RESOURCE_GROUP}
kubectl config current-context

Ingress デプロイ

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.41.0/deploy/static/provider/cloud/deploy.yaml

ingress-nginxLoadBalancerEXTERNAL-IP が割り当てられるまで待つ。

bash-5.0# kubectl get pods --namespace ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-fcfvr        0/1     Completed   0          55s
ingress-nginx-admission-patch-zxkjf         0/1     Completed   0          55s
ingress-nginx-controller-7c6c46898c-gbgsk   1/1     Running     0          56s
bash-5.0# kubectl get services --namespace ingress-nginx
NAME                                 TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.0.38.32    20.48.68.182   80:30680/TCP,443:32484/TCP   78s
ingress-nginx-controller-admission   ClusterIP      10.0.14.233   <none>         443/TCP                      78s```

Ingress の公開 IP アドレスをメモ。

```sh
DOMAIN_IP=$(kubectl get services --namespace ingress-nginx -o jsonpath='{.items[].status.loadBalancer.ingress[0].ip}')
DOMAIN="$(echo ${DOMAIN_IP} | sed -e "s/\./-/g").nip.io"

自己証明書の作成

新しく openssl コンテナを立ち上げて、その中で証明書を作成する。

cd ${WORK_DIR}
mkdir che_demo_ca
cd .\che_demo_ca

curl https://raw.githubusercontent.com/mikoto2000/docker-images/2fb7b9f119f65aec12ccc8db364bebeba8201090/openssl/docker-compose.yml -OutFile .\docker-compose.yml
mkdir usr_lib_ssl
curl https://raw.githubusercontent.com/mikoto2000/docker-images/2fb7b9f119f65aec12ccc8db364bebeba8201090/openssl/usr_lib_ssl/openssl.cnf -OutFile .\usr_lib_ssl\openssl.cnf
curl https://raw.githubusercontent.com/mikoto2000/docker-images/2fb7b9f119f65aec12ccc8db364bebeba8201090/openssl/usr_lib_ssl/v3_ca.txt -OutFile .\usr_lib_ssl\v3_ca.txt
docker-compose run --rm openssl bash

コンテナ内で証明書作成

# 必要な情報整理

## ドメイン定義
DOMAIN_IP="20.194.178.18"
DOMAIN="$(echo ${DOMAIN_IP} | sed -e "s/\./-/g").nip.io"

## SAN 設定作成
echo "subjectAltName = @alt_names" >> ./usr_lib_ssl/v3.txt
echo "" >> ./usr_lib_ssl/v3.txt
echo "[ alt_names ]" >> ./usr_lib_ssl/v3.txt
echo "DNS.1 = "'*'".${DOMAIN}" >> ./usr_lib_ssl/v3.txt

## 各種生成物定義
CA_KEY_FILE="/ca/private/cakey.pem"
CA_CSR_FILE="/ca/ca.csr"
CA_CRT_FILE="/ca/cacert.pem"

CA_COUNTRY="JP"
CA_STATE="KEN"
CA_LOCALITY="KU"
CA_ORGANIZATION="KOJIN"
CA_ORGANIZATION_UNIT="NONE"
CA_COMMON="${DOMAIN}"
CA_EMAIL="mikoto2000@gmail.com"


# CA 初期化
cd /ca

## 各種ディレクトリ作成
mkdir cert private crl newcerts
chmod 700 private

## シリアル初期化
echo "01" | tee -a serial

## crlnumber 初期化
echo "01" | tee -a crlnumber

## インデックス初期化
touch index.txt
echo "unique_subjec = yes" > index.txt.attr


# CA 鍵と CA 証明書作成

## CA 用秘密鍵作成
openssl genrsa -out ${CA_KEY_FILE} 2048

## CA 証明書要求作成
CA_SUBJECT="/C=${CA_COUNTRY}/ST=${CA_STATE}/L=${CA_LOCALITY}/O=${CA_ORGANIZATION}/OU=${CA_ORGANIZATION_UNIT}/CN=${CA_COMMON}"
openssl req -new -key ${CA_KEY_FILE} -out ${CA_CSR_FILE} -subj "${CA_SUBJECT}"

## CA 証明書要求確認
openssl req -noout -text -in ${CA_CSR_FILE}

## CA 証明書作成
openssl x509 -days 365 -req -in ${CA_CSR_FILE} -signkey ${CA_KEY_FILE} -out ${CA_CRT_FILE} -extfile /usr/lib/ssl/v3_ca.txt

## CA 証明書確認
openssl x509 -text -noout -in ${CA_CRT_FILE}

## CA 証明書を out ディレクトリへコピー
cp ${CA_CRT_FILE} /client/ca.crt


# サーバー証明書発行
SERVER_COMMON="${DOMAIN}"
SERVER_KEY_FILE="/client/server-${SERVER_COMMON}.key"
SERVER_CSR_FILE="/client/server-${SERVER_COMMON}.csr"
SERVER_CRT_FILE="/client/server-${SERVER_COMMON}.crt"

SERVER_COUNTRY="JP"
SERVER_STATE="KEN"
SERVER_LOCALITY="KU"
SERVER_ORGANIZATION="KOJIN"
SERVER_ORGANIZATION_UNIT="NONE"
SERVER_COMMON="server-${DOMAIN}"
SERVER_EMAIL="mikoto2000@gmail.com"

## サーバー秘密鍵作成
openssl genrsa -out ${SERVER_KEY_FILE} 2048

## サーバー証明書要求作成
SERVER_SUBJECT="/C=${SERVER_COUNTRY}/ST=${SERVER_STATE}/L=${SERVER_LOCALITY}/O=${SERVER_ORGANIZATION}/OU=${SERVER_ORGANIZATION_UNIT}/CN=${SERVER_COMMON}"
openssl req -new -key ${SERVER_KEY_FILE} -out ${SERVER_CSR_FILE} -subj "${SERVER_SUBJECT}"

## クライアント証明書要求確認
openssl req -noout -text -in ${SERVER_CSR_FILE}


# サーバー証明書作成
cd /client
yes | openssl ca -out ${SERVER_CRT_FILE} -extfile /usr/lib/ssl/v3.txt -infiles ${SERVER_CSR_FILE}


# ホスト証明書発行
HOST_COMMON="${DOMAIN}"
HOST_KEY_FILE="/client/host-${HOST_COMMON}.key"
HOST_CSR_FILE="/client/host-${HOST_COMMON}.csr"
HOST_CRT_FILE="/client/host-${HOST_COMMON}.crt"

HOST_COUNTRY="JP"
HOST_STATE="KEN"
HOST_LOCALITY="KU"
HOST_ORGANIZATION="KOJIN"
HOST_ORGANIZATION_UNIT="NONE"
HOST_COMMON="host-${DOMAIN}"
HOST_EMAIL="mikoto2000@gmail.com"

## ホスト秘密鍵作成
openssl genrsa -out ${HOST_KEY_FILE} 2048

## ホスト証明書要求作成
HOST_SUBJECT="/C=${HOST_COUNTRY}/ST=${HOST_STATE}/L=${HOST_LOCALITY}/O=${HOST_ORGANIZATION}/OU=${HOST_ORGANIZATION_UNIT}/CN=${HOST_COMMON}"
openssl req -new -key ${HOST_KEY_FILE} -out ${HOST_CSR_FILE} -subj "${HOST_SUBJECT}"

## クライアント証明書要求確認
openssl req -noout -text -in ${HOST_CSR_FILE}


# ホスト証明書作成
cd /client
yes | openssl ca -out ${HOST_CRT_FILE} -extfile /usr/lib/ssl/v3.txt -infiles ${HOST_CSR_FILE}

Kubernetes へ自己証明書を登録

kubectl create namespace che
kubectl create secret generic self-signed-certificate --from-file=che_demo_ca/client/ca.crt -n che
kubectl create secret generic che-tls --from-file=ca.crt=che_demo_ca/client/ca.crt --from-file=tls.key=che_demo_ca/client/server-${DOMAIN}.key --from-file=tls.crt=che_demo_ca/client/server-${DOMAIN}.crt -n che

Eclipse Che のインストール

git clone --depth 1 https://github.com/eclipse/che
cd che/deploy/kubernetes/helm/che/

# マルチユーザーモード
sed -i -e 's/  multiuser: false/  multiuser: true/g' values.yaml

# TLS 有効化
sed -i -e 'N;N;s/  tls:\n    enabled: false/  tls:\n    enabled: true/g' values.yaml

# PVC の作成単位をワークスペースごとに修正
sed -i -e 's/  cheWorkspacesPVCStrategy: "common"/  cheWorkspacesPVCStrategy: "per-workspace"/g' values.yaml

# PVC の容量アップ
sed -i -e 's/  pvcClaim: "1Gi"/  pvcClaim: "10Gi"/g' values.yaml

# 1 ユーザーごとに 10 個ワークスペースを作れるように修正
sed -i -e 's/    # userWorkspacesRunCount/    userWorkspacesRunCount: 10/g' values.yaml

# シングルホストモード有効化
sed -i -e 's/serverStrategy: multi-host/serverStrategy: single-host/g' values.yaml
sed -i -e 's/  singleHostExposure: native/  singleHostExposure: gateway/g' values.yaml
sed -i -e 's/  deploy: false/  deploy: true/g' values.yaml

# デプロイ
helm dependency update
kubectl create namespace che
helm upgrade --install che --namespace che --set global.ingressDomain=myide.${DOMAIN} ./

kubectl get pods で che の Pod が立ち上がったことを確認したら、以下 URL でアクセスできる。

  • Keycloak: https://myide.20-194-178-18.nip.io/auth/
  • Che: https://myide.20-194-178-18.nip.io/dashboard/

以上。

参考資料

2021年4月14日水曜日

AWS + kops + nip.io で Eclipse Che を動かす

Installing Che on AWS :: Eclipse Che Documentation の手順をベースにやってみる。

差分は以下。

  • DNS は nip.io を利用
  • HTTPS 化はしない
  • シングルユーザーモード
  • chectl を使わず、 helm チャートでデプロイ

前提

  • OS: Windows 10 Pro
  • Docker: Docker version 20.10.5, build 55c4c88
  • AWS アカウント作成済み

IAM キーの作成

とりあえずルートユーザーのアクセスキーを作ってそれを使用する。

本来なら IAM ユーザーに適切な権限を付与したうえで、その人のアクセスキーを作成するべきらしい。

  1. AWS マネジメントコンソールに「ルートユーザー」としてログイン
  2. 右上のアカウント名 -> マイセキュリティ資格情報 -> アクセスキー (アクセスキー ID とシークレットアクセスキー) -> 新しいアクセスキーの作成 を押下
  3. キーファイルのダウンロード

あとで使うので適切な場所に保存しておく。

必要なツールの準備

今回は、 mikoto2000/eks-tools を使用し、足りないツールを継ぎ足していく。

mikoto2000/eks-tools には、以下ツールがインストール済み。

  • AWS CLI
  • kubectl
  • helm

コンテナ起動後、足りないツール類をインストールする。

docker run -it --rm mikoto2000/eks-tools

kops のインストール

Installing Kubernetes with kops | Kubernetes に kops のインストール手順が記載されているので、その通りに実行。

curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-linux-amd64
chmod +x kops-linux-amd64
mv kops-linux-amd64 /usr/local/bin/kops

ssh のインストール

kops で Kubernetes クラスターへ接続するための SSH 鍵を作成するために、 ssh をインストール。

ついでに鍵作成もしておく。

yum install openssh-clients
ssh-keygen

bind-utils のインストール

ingress の EXTERNAL-IP(ホスト名) から IP アドレスを取得するために dig コマンドを使いたいのでインストール。

yum install bind-utils

git のインストール

Eclipse Che のデプロイ関連ソース取得のため。

yum install git

AWS の環境構築

aws-cli の設定

aws configure コマンドで、 IAM キー情報とリージョン・出力形式を設定する。

bash-4.2# aws configure
AWS Access Key ID [None]: xxxxxxxxxxxxxxxxxxxx
AWS Secret Access Key [None]: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
Default region name [None]: ap-northeast-1
Default output format [None]: json

SSH 鍵作成

ssh-keygen

kops 管理情報保存用の s3 を作成

aws s3 mb s3://eclipse-che-kops-state-store
export KOPS_STATE_STORE=s3://eclipse-che-kops-state-store

Kubernetes クラスターの作成

kops を使って Kubernetes クラスターを作成する。

kops create secret --name eclipse-che.k8s.local sshpublickey admin -i ~/.ssh/id_rsa.pub
kops create cluster --zones=ap-northeast-1a --name eclipse-che.k8s.local
kops update cluster eclipse-che.k8s.local --yes
kops export kubecfg --admin

作成したクラスタの確認。

クラスタ起動が完了すると、 kops validate cluster で情報が返ってくる。

$ kops validate cluster --wait 10m
Using cluster from kubectl context: eclipse-che.k8s.local

Validating cluster eclipse-che.k8s.local

INSTANCE GROUPS
NAME                    ROLE    MACHINETYPE     MIN     MAX     SUBNETS
master-ap-northeast-1a  Master  t3.medium       1       1       ap-northeast-1a
nodes-ap-northeast-1a   Node    t3.medium       1       1       ap-northeast-1a

NODE STATUS
NAME                                                    ROLE    READY
ip-172-20-41-193.ap-northeast-1.compute.internal        node    True
ip-172-20-54-87.ap-northeast-1.compute.internal         master  True

Your cluster eclipse-che.k8s.local is ready

あとは kubectl で操作できる。

bash-4.2# kubectl get pods --all-namespaces
NAMESPACE     NAME                                                                      READY   STATUS    RESTARTS   AGE
kube-system   coredns-5489b75945-pvlp6                                                  1/1     Running   0          10m
kube-system   coredns-5489b75945-rtspc                                                  1/1     Running   0          12m
kube-system   coredns-autoscaler-6f594f4c58-8pz6n                                       1/1     Running   0          12m
kube-system   dns-controller-8574dcc89d-nst7k                                           1/1     Running   0          12m
kube-system   etcd-manager-events-ip-172-20-54-87.ap-northeast-1.compute.internal       1/1     Running   0          11m
kube-system   etcd-manager-main-ip-172-20-54-87.ap-northeast-1.compute.internal         1/1     Running   0          11m
kube-system   kops-controller-gnwrh                                                     1/1     Running   0          11m
kube-system   kube-apiserver-ip-172-20-54-87.ap-northeast-1.compute.internal            2/2     Running   0          11m
kube-system   kube-controller-manager-ip-172-20-54-87.ap-northeast-1.compute.internal   1/1     Running   0          11m
kube-system   kube-proxy-ip-172-20-41-193.ap-northeast-1.compute.internal               1/1     Running   0          10m
kube-system   kube-proxy-ip-172-20-54-87.ap-northeast-1.compute.internal                1/1     Running   0          11m
kube-system   kube-scheduler-ip-172-20-54-87.ap-northeast-1.compute.internal            1/1     Running   0          12m

Ingress のインストール

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.41.0/deploy/static/provider/aws/deploy.yaml

ingress-nginx-congroller が実行中になることを確認。

bash-4.2# kubectl get pods --all-namespaces
NAMESPACE       NAME                                                                      READY   STATUS      RESTARTS   AGE
ingress-nginx   ingress-nginx-admission-create-khwmz                                      0/1     Completed   0          12m
ingress-nginx   ingress-nginx-admission-patch-4d2rh                                       0/1     Completed   0          12m
ingress-nginx   ingress-nginx-controller-85b8d88cf5-6jwvb                                 1/1     Running     0          12m
kube-system     coredns-5489b75945-pvlp6                                                  1/1     Running     0          26m
kube-system     coredns-5489b75945-rtspc                                                  1/1     Running     0          27m
kube-system     coredns-autoscaler-6f594f4c58-8pz6n                                       1/1     Running     0          27m
kube-system     dns-controller-8574dcc89d-nst7k                                           1/1     Running     0          27m
kube-system     etcd-manager-events-ip-172-20-54-87.ap-northeast-1.compute.internal       1/1     Running     0          26m
kube-system     etcd-manager-main-ip-172-20-54-87.ap-northeast-1.compute.internal         1/1     Running     0          27m
kube-system     kops-controller-gnwrh                                                     1/1     Running     0          26m
kube-system     kube-apiserver-ip-172-20-54-87.ap-northeast-1.compute.internal            2/2     Running     0          26m
kube-system     kube-controller-manager-ip-172-20-54-87.ap-northeast-1.compute.internal   1/1     Running     0          26m
kube-system     kube-proxy-ip-172-20-41-193.ap-northeast-1.compute.internal               1/1     Running     0          26m
kube-system     kube-proxy-ip-172-20-54-87.ap-northeast-1.compute.internal                1/1     Running     0          26m
kube-system     kube-scheduler-ip-172-20-54-87.ap-northeast-1.compute.internal            1/1     Running     0          27m

外部公開 IP アドレスをメモ。

CHE_HOST_NAME="$(kubectl get services --namespace ingress-nginx -o jsonpath='{.items[].status.loadBalancer.ingress[0].hostname}')"
DOMAIN_IP="$(dig +short $CHE_HOST_NAME)"
DOMAIN="$(echo ${DOMAIN_IP} | sed -e "s/\./-/g").nip.io"

Eclipse Che のデプロイ

nightly が動かなかったので 7.27.0 をデプロイ。

git clone --depth 1 https://github.com/eclipse/che
cd che/deploy/kubernetes/helm/che/
sed -i -e "s/quay.io\/eclipse\/che-devfile-registry:nightly/quay.io\/eclipse\/che-devfile-registry:7.27.0/" custom-charts/che-devfile-registry/values.yaml
sed -i -e "s/quay.io\/eclipse\/che-plugin-registry:nightly/quay.io\/eclipse\/che-plugin-registry:7.27.0/" custom-charts/che-plugin-registry/values.yaml
helm dependency update
kubectl create namespace che
helm upgrade --install che --namespace che --set global.cheWorkspacesNamespace="che" --set cheImage="quay.io/eclipse/che-server:7.27.0" --set dashboard.image="quay.io/eclipse/che-dashboard:7.27.0" --set global.ingressDomain=${DOMAIN} ./

kubectl get pods で che の Pod が立ち上がったことを確認。

bash-4.2# kubectl get pods -n che
NAME                                READY   STATUS    RESTARTS   AGE
che-56bddc9f89-5czv2                1/1     Running   0          83s
che-dashboard-649cb64655-cv9zm      1/1     Running   0          83s
devfile-registry-7f5f8fdf4d-4b88t   1/1     Running   0          83s
plugin-registry-558796b4bd-d9wm5    1/1     Running   0          83s

ブラウザで che-che.$DOMAIN にアクセス。

以上。

HTTP 通信・シングルユーザーモードでデプロイしているので、速やかに削除。

kops delete cluster eclipse-che.k8s.local --yes
aws s3 rb s3://eclipse-che-kops-state-store

ルートユーザーのアクセスキーの削除も忘れず行う。

参考資料