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

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

参考資料

2021年3月24日水曜日

Debian 11 で Rootless Podman を試す

Debian 11 だと apt でインストールできるようなので、それでサクッと試す。

前提条件

Podman のインストール

pull 時に TLS 通信が使われるので、 ca-certificates もインストールする。

sudo apt-get update
sudo apt-get install -y podman ca-certificates

とりあえず rootfull で podman が実行できることを確認。

mikoto@debian:~$ sudo podman run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

OK.

Rootless のための準備

一般ユーザーが名前空間を作成できるようにカーネルパラメーターを更新。

sudo bash -c 'echo "user.max_user_namespaces=28633" > /etc/sysctl.d/userns.conf'
sudo sysctl -p /etc/sysctl.d/userns.conf

この後作成するユーザーについては、rootless podman を実行するための設定が有効になる。

現在のログインユーザーが、名前空間を作成できるようにするためには、マシンの再起動が必要。 (他に方法があると思うが、今回再ログインでもダメだったので再起動した…)

動作確認

mikoto@debian:~$ podman run hello-world
Resolved "hello-world" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
Trying to pull docker.io/library/hello-world:latest...
Getting image source signatures
Copying blob b8dfde127a29 done
Copying config d1165f2212 done
Writing manifest to image destination
Storing signatures

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

以上。

参考資料