ラベル Azure の投稿を表示しています。 すべての投稿を表示
ラベル Azure の投稿を表示しています。 すべての投稿を表示

2021年5月3日月曜日

Eclipse Che と Azure Firewall を組み合わせて使いたかったけどダメだった。

Azure Kubernetes Service (AKS) でエグレス トラフィックを制限する - Azure Kubernetes Service | Microsoft Docs をベースに Eclipse Che をデプロイしたが、 Pod が Public IP へアクセスしたときのルーティングがうまくいかずに動作させることができなかった。

Eclipse Che のことは置いておくとして、 AKS と Firewall の組み合わせ手順の備忘。

前提条件

  • OS: Windows 10 Pro
  • Docker Desktop インストール済み
  • DNS に nip.io を利用
  • Docker: Docker version 20.10.5, build 55c4c88

作業用 Docker コンテナを起動

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

必要なツール類をインストール

bind-tools

dig を使うため。

apk add bind-tools

chectl

デプロイに使用。

apk add nodejs
bash <(curl -sL  https://www.eclipse.org/che/chectl/)

設定ファイル編集に使用

apk add vim
export EDITOR="vim"

必要な azure-cli 拡張機能をインストール

az extension add --name aks-preview
az extension add --name azure-firewall

作業手順

必要な情報の整理

# ログイン
az login

## 基本?情報
# サブスクリプション ID
SUBID=$(az account show --query id -o tsv)
PREFIX="eclipse-che1"
LOC="japaneast"
PLUGIN="azure"

# リソースグループ名
RG="${PREFIX}-rg"
# AKS 名
AKSNAME="${PREFIX}"

## 仮想ネットワーク
# AKS と Firewall を配置するサブネット
VNET_NAME="${PREFIX}-vnet"
# AKS 用サブネット名
AKSSUBNET_NAME="aks-subnet"
# Firewall 用サブネット名。 Azure Firewall の要件なので、名前の変更不可。
FWSUBNET_NAME="AzureFirewallSubnet"

## Firewall
# Firewall 名
FWNAME="${PREFIX}-fw"
# Firewall の外部 IP 名
FWPUBLICIP_NAME="${PREFIX}-fwpublicip"
# Firewall の設定情報名
FWIPCONFIG_NAME="${PREFIX}-fwconfig"

## ルーティングテーブル
# ルーティングテーブル名
FWROUTE_TABLE_NAME="${PREFIX}-fwrt"
# ルート名。 AKS から Firewall 内部 IP へのルーティング
FWROUTE_NAME="${PREFIX}-fwrn"
# ルート名。 Firewall インターネットへのルーティング
FWROUTE_NAME_INTERNET="${PREFIX}-fwinternet"

## プライベート DNS ゾーン
#PDZ_DOMAIN="nip.io"
#PDZ_LINK_NAME="${PREFIX}-pdz-link"

リソースグループの作成

az group create --name $RG --location $LOC

仮想ネットワーク作成

仮想ネットワークと、 AKS 用サブネットの作成

az network vnet create \
    --resource-group $RG \
    --name $VNET_NAME \
    --location $LOC \
    --address-prefixes 10.42.0.0/16 \
    --subnet-name $AKSSUBNET_NAME \
    --subnet-prefix 10.42.1.0/24

仮想ネットワークに、 Firewall 用のサブネットを追加

az network vnet subnet create \
    --resource-group $RG \
    --vnet-name $VNET_NAME \
    --name $FWSUBNET_NAME \
    --address-prefix 10.42.2.0/24

Firewall を配置

Eclipse Che の出入り口となるパブリック IP アドレスを作成

az network public-ip create -g $RG -n $FWPUBLICIP_NAME -l $LOC --sku "Standard"

Firewall を作成

以下コマンドで、 Firewall リソースを作成。

az network firewall create -g $RG -n $FWNAME -l $LOC --enable-dns-proxy true

Firewall をサブネットへ配置してパブリック IP を割り当てる

以下コマンドで、サブネットへの配置と、パブリック IP の割り当てを実行。 この時点で Firewall のプライベート IP も自動生成される。

az network firewall ip-config create -g $RG -f $FWNAME -n $FWIPCONFIG_NAME --public-ip-address $FWPUBLICIP_NAME --vnet-name $VNET_NAME

生成された IP を記録

以下コマンドで、パブリック IP とプライベート IP を記録。

FWPUBLIC_IP=$(az network public-ip show -g $RG -n $FWPUBLICIP_NAME --query "ipAddress" -o tsv)
FWPRIVATE_IP=$(az network firewall show -g $RG -n $FWNAME --query "ipConfigurations[0].privateIpAddress" -o tsv)

ルーティングテーブル(UDR: User Defined Routing)の作成・設定

ルートテーブル作成

以下コマンドで、ルートテーブルを作成。

az network route-table create -g $RG -l $LOC --name $FWROUTE_TABLE_NAME

ルーティングルールを追加

ルートテーブルに、ルールを追加する。

ここの FW → インターネットのルーティングの意味が良くわかっていないが、こすると外向きの通信がインターネットへ届くようになるようだ。

# AKS 用サブネット → FW プライベート IP
az network route-table route create -g $RG --name $FWROUTE_NAME --route-table-name $FWROUTE_TABLE_NAME --address-prefix 0.0.0.0/0 --next-hop-type VirtualAppliance --next-hop-ip-address $FWPRIVATE_IP --subscription $SUBID
# FW → インターネット
az network route-table route create -g $RG --name $FWROUTE_NAME_INTERNET --route-table-name $FWROUTE_TABLE_NAME --address-prefix $FWPUBLIC_IP/32 --next-hop-type Internet

ルートテーブルを適用

仮想ネットワークにルートテーブルを適用する。

az network vnet subnet update -g $RG --vnet-name $VNET_NAME --name $AKSSUBNET_NAME --route-table $FWROUTE_TABLE_NAME

アクセス権設定

AKS が各種リソースを生成・配置できるように、権限を付与したサービスプリンシパルを作成しておく。

サービスプリンシパル作成

az ad sp create-for-rbac -n "${PREFIX}sp" --skip-assignment

表示された appIdpassword を記録。

APPID="xxxxxxxx-xxxx-xxxxxxxxx-ssssssssssss"
PASSWORD="yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"

サービスプリンシパルにロールを設定

仮想ネットワークを操作できる権限を、サービスプリンシパルへ割り当てる。

VNETID=$(az network vnet show -g $RG --name $VNET_NAME --query id -o tsv)
az role assignment create --assignee $APPID --scope $VNETID --role "Network Contributor"

Firewall の規則を追加

先ほど生成された IP アドレスを使って、規則を作成する。

Azure Global に必要なネットワーク規則 を追加

az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'apiudp' --protocols 'UDP' --source-addresses '*' --destination-addresses "AzureCloud.$LOC" --destination-ports 1194 --action allow --priority 100
az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'apitcp' --protocols 'TCP' --source-addresses '*' --destination-addresses "AzureCloud.$LOC" --destination-ports 9000
az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'time' --protocols 'UDP' --source-addresses '*' --destination-fqdns 'ntp.ubuntu.com' --destination-ports 123

az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'aksfwar' -n 'fqdn' --source-addresses '*' --protocols 'http=80' 'https=443' --fqdn-tags "AzureKubernetesService" --action allow --priority 100
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'aksfwar' -n 'japaneast' --source-addresses '*' --protocols 'https=443' --target-fqdns 'japaneast.monitoring.azure.com'

Azure Monitor に必要な規則。

az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'monitor' --protocols 'TCP' --source-addresses '*' --destination-addresses "AzureMonitor.$LOC" --destination-ports 443

コンテナイメージ Pull のために必要な規則。

# docker
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'container-registry' -n 'docker-io' --source-addresses '*' --protocols 'http=80' 'https=443' --target-fqdns '*.docker.io' 'production.cloudflare.docker.com' --action allow --priority 200

# k8s.gcr.io
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'container-registry' -n 'k8s-gcr-io' --source-addresses '*' --protocols 'http=80' 'https=443' --target-fqdns 'k8s.gcr.io' 'storage.googleapis.com'

# quay.io
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'container-registry' -n 'quay-io' --source-addresses '*' --protocols 'http=80' 'https=443' --target-fqdns 'quay.io' '*.quay.io'

# registry.access.redhat.com
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'container-registry' -n 'registry-access-redhat-com' --source-addresses '*' --protocols 'http=80' 'https=443' --target-fqdns 'registry.access.redhat.com'

helm チャート取得のために必要な規則。

# grafan
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'che' -n 'grafan' --source-addresses '*' --protocols 'https=443' --target-fqdns 'grafana.github.io' --action allow --priority 300

# prometheus
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'che' -n 'prometheus' --source-addresses '*' --protocols 'http=80' 'https=443' --target-fqdns 'prometheus-community.github.io'

Theia プラグインダウンロードに必要な規則。

# github
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'theia-plugin' -n 'github-io' --source-addresses '*' --protocols 'https=443' --target-fqdns 'github.com' 'github-releases.githubusercontent.com' --action allow --priority 400

Kubernetes クラスターをデプロイする

AKS 用サブネットへ、 Kubernetes クラスターをデプロイする。

SUBNETID=$(az network vnet subnet show -g $RG --vnet-name $VNET_NAME --name $AKSSUBNET_NAME --query id -o tsv)

az aks create -g $RG -n $AKSNAME -l $LOC \
  --node-vm-size Standard_DS2_v2 \
  --node-count 1 \
  --generate-ssh-keys \
  --enable-addons monitoring \
  --enable-managed-identity \
  --network-plugin $PLUGIN \
  --outbound-type userDefinedRouting \
  --service-cidr 10.41.0.0/16 \
  --dns-service-ip 10.41.0.10 \
  --docker-bridge-address 172.17.0.1/16 \
  --vnet-subnet-id $SUBNETID \
  --service-principal $APPID \
  --client-secret $PASSWORD

az aks get-credentials --name ${AKSNAME} --resource-group ${RG}

kubectl get pods -n kube-system

Ingress をデプロイ

helm が Kubernetes クラスタの API へアクセスできるように Firewall ルールを追加する

AKSFQDN=$(az aks show -g $RG -n $AKSNAME --query fqdn -o tsv)
AKSIP=$(dig $AKSFQDN +short)

az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'apiserver' --protocols 'TCP' --source-addresses '*' --destination-addresses "$AKSIP" --destination-ports 443

Ingress 用 Public IP の作成

INGRESS_IP_ADDRESS_NAME="${PREFIX}-ingresspublicip"
az network public-ip create -g $RG --name $INGRESS_IP_ADDRESS_NAME --sku Standard --allocation-method static
INGRESS_IP_ADDRESS=$(az network public-ip show -g $RG --name $INGRESS_IP_ADDRESS_NAME --query ipAddress -o tsv)

サービスプリンシパル作成

AKS_CLIENT_ID=$(az aks show -g $RG -n $AKSNAME --query "servicePrincipalProfile.clientId" -o tsv)

az role assignment create \
    --assignee $AKS_CLIENT_ID \
    --role "Network Contributor" \
    --scope /subscriptions/$SUBID/resourceGroups/$RG

helm による Ingress デプロイ

DNS_LABEL="ingress"

kubectl create namespace ingress-nginx

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

helm upgrade --install nginx-ingress ingress-nginx/ingress-nginx \
    --namespace ingress-nginx \
    --set controller.replicaCount=1 \
    --set controller.nodeSelector."beta\.kubernetes\.io/os"=linux \
    --set defaultBackend.nodeSelector."beta\.kubernetes\.io/os"=linux \
    --set controller.admissionWebhooks.patch.nodeSelector."beta\.kubernetes\.io/os"=linux \
    --set controller.service.loadBalancerIP="$INGRESS_IP_ADDRESS" \
    --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"="$DNS_LABEL" \
    --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-resource-group"="$RG"

Ingress の EXTERNAL-IP を記録。

INGRESS_IP=$(kubectl get services --namespace ingress-nginx -o jsonpath='{.items[].status.loadBalancer.ingress[0].ip}')

Firewall から Ingress へつなげる DNAT 設定を行う

az network firewall nat-rule create --collection-name ingress --destination-addresses $FWPUBLIC_IP --destination-ports 80 --firewall-name $FWNAME --name http --protocols Any --resource-group $RG --source-addresses '*' --translated-port 80 --action Dnat --priority 200 --translated-address $INGRESS_IP
az network firewall nat-rule create --collection-name ingress --destination-addresses $FWPUBLIC_IP --destination-ports 443 --firewall-name $FWNAME --name https --protocols Any --resource-group $RG --source-addresses '*' --translated-port 443 --translated-address $INGRESS_IP

この時点で $FWPUBLIC_IP に接続すると、 NGINX の 404 Not Found 画面が表示される。

Eclipse Che のデプロイ

以降、 AKS 操作用 VM 上での作業。

Eclipse Che リポジトリのクローン

クローンして helm デプロイ用のディレクトリへ移動。

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

chectl による Eclipse Che のデプロイ

INGRESS_DOMAIN="$(echo $FWPUBLIC_IP | sed -e "s/\./-/g").nip.io"
chectl server:deploy -n che --installer=helm --platform=k8s --helm-patch-yaml=values.yaml --domain=webide.$INGRESS_DOMAIN --multiuser

以下のようなメッセージが表示される。

Show important messages
Eclipse Che 7.30.0-SNAPSHOT has been successfully deployed.
Documentation             : https://www.eclipse.org/che/docs/
-------------------------------------------------------------------------------
Users Dashboard           : http://webide.20-48-87-43.nip.io
Admin user login          : "admin:admin". NOTE: must change after first login.
-------------------------------------------------------------------------------
Plug-in Registry          : http://webide.20-48-87-43.nip.io/plugin-registry/v3
Devfile Registry          : http://webide.20-48-87-43.nip.io/devfile-registry
-------------------------------------------------------------------------------
Identity Provider URL     : http://webide.20-48-87-43.nip.io/auth
Identity Provider login   : "admin:gOlU40cdAiKe".
-------------------------------------------------------------------------------
    ✔ [ACTION REQUIRED] Please add Che self-signed CA certificate into your browser: /tmp/cheCA.crt.
   Documentation how to add a CA certificate into a browser: https://www.eclipse.org/che/docs/che-7/end-user-guide/impor
ting-certificates-to-browsers/
Command server:deploy has completed successfully in 08:52.

http://webide.20-48-87-43.nip.io/dashboard へログインして適当なワークスペースを起動してみる。

エラー。

デバッグ情報を表示して再挑戦。

values.yaml の以下項目で変更できると思っていたのだけど、なぜか反映されなかった…。

  • logLevel: "INFO" -> logLevel: "DEBUG"
  • loggerConfig: "" -> loggerConfig: "org.eclipse.che.api.workspace.server.WorkspaceManager=DEBUG,che.infra.request-logging=DEBUG,org.eclipse.che.api.workspace.server.hc.HttpConnectionServerChecker=DEBUG"

なので、 ConfigMap を手動で修正する。

kubectl edit cm -n che

ConfigMap を以下のように修正。

  • CHE_LOG_LEVELL: INFO -> CHE_LOG_LEVELL: DEBUG
  • CHE_LOGGER_CONFIG: "" -> CHE_LOGGER_CONFIG: "org.eclipse.che.api.workspace.server.WorkspaceManager=TRACE,che.infra.request-logging=TRACE,org.eclipse.che.api.workspace.server.hc.HttpConnectionServerChecker=TRACE"

リスタート。

kubectl rollout restart -n che             deployments/che
kubectl rollout restart -n che             deployments/che-dashboard
kubectl rollout restart -n che             deployments/devfile-registry
kubectl rollout restart -n che             deployments/keycloak
kubectl rollout restart -n che             deployments/plugin-registry
kubectl rollout restart -n che             deployments/postgres
kubectl rollout restart -n ingress-nginx   deployments/nginx-ingress-ingress-nginx-controller

今度は verbose mode でワークスペースを起動。

websocket 通信に、Firewall Public IP のアドレスが使われている。

Azure Firewall はプライベート IP からプライベート IP への DNAT に対応していないようだ…?

https://docs.microsoft.com/ja-jp/azure/firewall/overview#known-issues より

CHE_WEBSOCKET_ENDPOINT, CHE_WEBSOCKET_ENDPOINT__MINOR の変更でインターナル通信できるようだ…?

https://github.com/eclipse-che/che-operator/pull/685/files#diff-83745225d10c6e28020233af5d16a2fa740200d2e15f56a70f054c167a579812R182-R184

もういちど ConfigMap を修正してリスタート。

ConfigMap を以下のように修正。

  • CHE_WEBSOCKET_ENDPOINT: ws://webide.20-48-87-43/api/websocket -> CHE_WEBSOCKET_ENDPOINT: ws://che-host.che.svc:8080/api/websocket
  • CHE_WEBSOCKET_ENDPOINT__MINOR: ws://webide.20-48-87-43/api/websocket-minor -> CHE_WEBSOCKET_ENDPOINT__MINOR: ws://che-host.che.svc:8080/api/websocket-minor

websocket は通ったが、コンテナ起動ができていない。

ログを見てもよくわからないので、勘で single-host から default-host に変更してやってみた。

ConfigMap を以下のように修正。

  • CHE_INFRA_KUBERNETES_SERVER__STRATEGY: single-host -> CHE_INFRA_KUBERNETES_SERVER__STRATEGY: default-host

再実行。

うーん、ワークスペースは起動するが、そこへ接続するための URL が INGRESS の IP アドレスになっていて、ブラウザから届かない感じか。

これは分からん…。

参考資料

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/

以上。

参考資料

2020年5月11日月曜日

自己証明書と nip.io を使って Eclipse Che を HTTPS 化する

ワンショットのデモをやることになったので、環境構築手順をメモ。

各種資材は 2019 年 10 月ごろのものなので最新化しなきゃ…

前提

Azure へログイン

PowerShell で mikoto2000/aks-tools イメージを起動。

mikoto2000/aks-tools コンテナ内でで Azure へログインする。

URL と code が表示される。Web ブラウザで表示された URL にアクセスし、 表示されたページのコード入力欄に code を入力。

Kubernetes クラスタ作成

mikoto2000/aks-tools コンテナ内ででクラスタを作成する。

Ingress デプロイ

ingress-nginx の LoadBalancer に EXTERNAL-IP が割り当てられるまで待つ。

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

証明書作成

下準備

mikoto2000/openssl を使用して証明書を作成。

コンテナ内で証明書作成

# 必要な情報整理

## ドメイン定義
DOMAIN_IP="20.37.126.225"
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 -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_COMMON}.key"
SERVER_CSR_FILE="/client/${SERVER_COMMON}.csr"
SERVER_CRT_FILE="/client/${SERVER_COMMON}.crt"

SERVER_COUNTRY="JP"
SERVER_STATE="KEN"
SERVER_LOCALITY="KU"
SERVER_ORGANIZATION="KOJIN"
SERVER_ORGANIZATION_UNIT="NONE"
SERVER_COMMON="${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}

DOMAIN_IP: mikoto2000/aks-tools でメモした EXTERNAL-IP

Kubernetes に証明書を設定

mikoto2000/aks-tools コンテナ内での作業。

デプロイ

ソースコード取得

tiller のインストール

che デプロイ

devfile-registry の修正

quay.io/eclipse/che-devfile-registry:nightly -> mikoto2000/che-devfile-registry:ET2019.

plugin-registry の修正

quay.io/eclipse/che-plugin-registry:nightly -> mikoto2000/che-plugin-registry:ET2019.

デプロイ

che-plugin-registryche-devfile-registry7.4.0 向けなので che-server もそれに合わせる。

動作確認

  1. 作成した ca.crt をブラウザにインポート
  2. https://che-keycloak.$DOMAIN へ接続して管理者設定・ユーザー追加
  3. https://che-che.$DOMAIN へ接続してログイン

余裕があったら別記事で手順を書く。

後片付け

mikoto2000/aks-tools で以下コマンドを実行。

以上。