Kubernetes(Kind)を使ってArgoCDからECK(Elastic Cloud on Kubernetes)デプロイしてみる
はじめに
少し前からKuberenetes入門しなければという使命感はあったものの、日常が忙しくどうしても入門できていなかったがやっと入門したので記録として残していきたいと思う。
今回は、KubernetesをDockerコンテナとして構築できるKindというツールを使って構築し、ArgoCDを使ってGithub上にあるリポジトリから構成を読んでECKをデプロイします。
いわゆるGitOpsでやっていきたい。
先週入門したばっかりなので、説明が間違っていたり設定が足りない部分があるかと思うがそこはご容赦いただきたい。
今回とりあえず構築まではできたので、Kuberenetesのスケーラビリティとか色々体感したい~。
Kind
説明は公式を読んでもらったほうが早いと思うので。
ArgoCD
Kubernetesで動かすことで、Gitのリポジトリ上に保存しているマニフェストファイルを監視して、変更があればKuberenetesにデプロイすることができる。すごい。
↓詳細はこちらを読んでもらったほうがいいと思う
ECK
Kubernetes上で動かすように構成されたElasticsearchとKibana。まだテクニカルプレビューであるものの、BeatsやFleetなども対応している。
基本的には、Kubernetesのマニフェストファイルをデプロイすることができるが、パッケージマネージャーであるHelmでのデプロイにも対応している。
↓公式サイト
構築
早速構築していきます。
- OS: Rocky Linux release 9.4 (Blue Onyx)
- RAM: 16GB
- CPU: 4 core
- IP: 192.168.2.143
また、hostsの編集でもいいので次の通りIPが引けるようにしておく。
- argocd.bira.local: 192.168.2.143
- kibana.bira.local: 192.168.2.143
netcatインストール
ログ取り込みテストに使います。
dnf install nc
Dockerのインストール
kindでDockerを使うため、Dokcerをインストールします。
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo systemctl start docker.service sudo systemctl enable docker.service
hello-worldして表示されればOKです。
[root@asdf ~]# docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c1ec31eb5944: Pull complete
Digest: sha256:a26bff933ddc26d5cdf7faa98b4ae1e3ec20c4985e6f87ac0973052224d24302
Status: Downloaded newer image for hello-world:latest
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/
[root@asdf ~]#
kubectlのインストール
Kubernetesをいじるためのコマンド。
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
バージョンが出ればOK
[root@asdf ~]# kubectl version --client Client Version: v1.30.0 Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
helmのインストール
Kubernetesのパッケージマネージャのようです。
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
help出ればOK
[root@asdf ~]# helm help The Kubernetes package manager Common actions for Helm: - helm search: search for charts - helm pull: download a chart to your local directory to view - helm install: upload the chart to Kubernetes - helm list: list releases of charts (省略)
ついでにリポジトリも追加しておきましょう。
[root@asdf ~]# helm repo add argo https://argoproj.github.io/argo-helm "argo" has been added to your repositories
kindのインストール
コンパイル済みバイナリを持ってくるのが一番楽でした。どうせ検証なので。
[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.22.0/kind-linux-amd64 chmod +x ./kind mv ./kind /usr/local/sbin/kind
コマンドが打てればOKです。
[root@asdf ~]# kind --help
kind creates and manages local Kubernetes clusters using Docker container 'nodes'
Usage:
kind [command]
Available Commands:
build Build one of [node-image]
completion Output shell completion code for the specified shell (bash, zsh or fish)
create Creates one of [cluster]
delete Deletes one of [cluster]
export Exports one of [kubeconfig, logs]
get Gets one of [clusters, nodes, kubeconfig]
help Help about any command
load Loads images into nodes
version Prints the kind CLI version
Flags:
-h, --help help for kind
--loglevel string DEPRECATED: see -v instead
-q, --quiet silence all stderr output
-v, --verbosity int32 info log verbosity, higher value produces more output
--version version for kind
Use "kind [command] --help" for more information about a command.
kindを使ったKubernetesの構築
適当に設定したうえで構築していきます。
[root@asdf ~]# cat >./kind-config.yaml <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 31111
hostPort: 31111
protocol: TCP
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- role: worker
- role: worker
EOF
[root@asdf ~]# kind create cluster --name kind --config ./kind-config.yaml
Creating cluster "kind" ...
✓ Ensuring node image (kindest/node:v1.29.2) 🖼
✓ Preparing nodes 📦 📦 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
✓ Joining worker nodes 🚜
Set kubectl context to "kind-kind"
You can now use your cluster with:
kubectl cluster-info --context kind-kind
Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂
Dockerのコンテナが作られていればOK
[root@asdf ~]# sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 86ec8bc836f7 kindest/node:v1.29.2 "/usr/local/bin/entr…" About a minute ago Up 59 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:31111->31111/tcp, 127.0.0.1:34729->6443/tcp kind-control-plane a2f1e0ce946a kindest/node:v1.29.2 "/usr/local/bin/entr…" About a minute ago Up 59 seconds kind-worker 3ef2f4254e3a kindest/node:v1.29.2 "/usr/local/bin/entr…" About a minute ago Up 59 seconds kind-worker2
今回作られたDockerの各コンテナはコントロールプレーンとノードと呼ばれるもの。本来3台に分けられるものを、コンテナとして作ってるっぽい。
Docker上で動いている都合上、いくつかポートが転送されています。これも後ほど使います。
Ingress Controllerのインストール
Kubernetes内のService(Podの集まり)に対してクラスタ外からの接続性を提供するヤツらしいです。HTTPとHTTPSのみですが、負荷分散等の機能がついているそうです。
今回は、ArgoCDとKibanaへのアクセスをこいつで設定してやります。
Ingress Controllerはあくまでもコントローラーのようですので、実設定は各マニフェスト側でやるようです。
[root@asdf ~]# kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml namespace/ingress-nginx created serviceaccount/ingress-nginx created serviceaccount/ingress-nginx-admission created role.rbac.authorization.k8s.io/ingress-nginx created role.rbac.authorization.k8s.io/ingress-nginx-admission created clusterrole.rbac.authorization.k8s.io/ingress-nginx created clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created rolebinding.rbac.authorization.k8s.io/ingress-nginx created rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created configmap/ingress-nginx-controller created service/ingress-nginx-controller created service/ingress-nginx-controller-admission created deployment.apps/ingress-nginx-controller created job.batch/ingress-nginx-admission-create created job.batch/ingress-nginx-admission-patch created ingressclass.networking.k8s.io/nginx created validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
一通り、podが動いていればOK。それまで必ず待つこと。
[root@asdf ~]# kubectl get pods -A NAMESPACE NAME READY STATUS RESTARTS AGE ingress-nginx ingress-nginx-admission-create-d9gfx 0/1 Completed 0 3m16s ingress-nginx ingress-nginx-admission-patch-c44mf 0/1 Completed 2 3m16s ingress-nginx ingress-nginx-controller-7b76f68b64-ngt5q 1/1 Running 0 3m16s kube-system coredns-76f75df574-prb6q 1/1 Running 0 41m kube-system coredns-76f75df574-r85z9 1/1 Running 0 41m kube-system etcd-kind-control-plane 1/1 Running 0 42m kube-system kindnet-2tpd4 1/1 Running 0 41m kube-system kindnet-mk8mc 1/1 Running 0 41m kube-system kindnet-vnzqm 1/1 Running 0 41m kube-system kube-apiserver-kind-control-plane 1/1 Running 0 42m kube-system kube-controller-manager-kind-control-plane 1/1 Running 0 42m kube-system kube-proxy-8s5fg 1/1 Running 0 41m kube-system kube-proxy-gp7bj 1/1 Running 0 41m kube-system kube-proxy-lwgwx 1/1 Running 0 41m kube-system kube-scheduler-kind-control-plane 1/1 Running 0 42m local-path-storage local-path-provisioner-7577fdbbfb-8nbbw 1/1 Running 0 41m
ArgoCDのインストール?
インストールという言葉が正しいかわからないが導入していく。
cat >./argocd-values.yaml <<EOF
global:
domain: argocd.bira.local
configs:
params:
server.insecure: true
server:
ingress:
enabled: true
ingressClassName: nginx
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
extraTls:
- hosts:
- argocd.bira.local
# Based on the ingress controller used secret might be optional
secretName: wildcard-tls
EOF
kubectl create namespace argocd
[root@asdf ~]# helm install argocd argo/argo-cd -n argocd --values ./argocd-values.yaml
NAME: argocd
LAST DEPLOYED: Sat May 11 15:29:59 2024
NAMESPACE: argocd
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
In order to access the server UI you have the following options:
1. kubectl port-forward service/argocd-server -n argocd 8080:443
and then open the browser on http://localhost:8080 and accept the certificate
2. enable ingress in the values file `server.ingress.enabled` and either
- Add the annotation for ssl passthrough: https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#option-1-ssl-passthrough
- Set the `configs.params."server.insecure"` in the values file and terminate SSL at your ingress: https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#option-2-multiple-ingress-objects-and-hosts
After reaching the UI the first time you can login with username: admin and the random password generated during the installation. You can find the password by running:
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
(You should delete the initial secret afterwards as suggested by the Getting Started Guide: https://argo-cd.readthedocs.io/en/stable/getting_started/#4-login-using-the-cli)
パスワード見えるよ!と書いてあるのでパスワードを見る。
[root@asdf ~]# kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
iIH-HlpbhZd-gR6H[root@asdf ~]#
ブラウザを起動して、https://argocd.bira.localにアクセスする。ユーザー名はadminでパスワードは先程のコマンドで確認したものを入力すればOK

ログインできればOK

ArgoCDでアプリケーションのインストール
ArgoCDのアプリケーションを追加するhelm chartがあるのでこれを使ってApplication
cat >./argocd-apps-values.yaml <<EOF
applications:
- name: argocd-root-app-of-apps
namespace: argocd
project: default
source:
repoURL: https://github.com/kbf09/kube-eck-test
targetRevision: main
path: apps
finalizers:
- resources-finalizer.argocd.argoproj.io
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
EOF
helm install argocd-apps argo/argocd-apps -n argocd \
--version 1.6.2 \
--values ./argocd-apps-values.yaml
もう一度、Web画面の方を見てみましょう。勝手にAppが作られていれば成功です。すべてがグリーンになるまで少し待ちましょう。

なんとこれで、Elasticsearchともろもろがインストールされてしまいました。設定はすべてgithub上から指定することができます。
kibanaへのアクセス
まずはパスワードを入手します。
kubectl get secret elasticsearch-es-elastic-user -o=jsonpath='{.data.elastic}' -n elastic-stack| base64 --decode; echo
0fHUvWZa6h6x3qg7728r1q1j
パスワードが分かれば、kibana.bira.localにアクセスしてログインします。

今回インストールしたElastic-StackはExampleの寄せ集めなのである程度インストールされています。実際に中身を見てみましょう。
Githubリポジトリ
今回はArgoCDがGithubリポジトリの中を参照して、おいてあるマニフェストファイルをベースに構築をします。どのようなファイルが置いてあるのか、確認して行きたいと思います。
eck-operator-crds
まずはKubenetes上のカスタムリソースを定義します。これはKubernetes APIの拡張らしく独自のオブジェクトを作ることができるそう。
Kubernetesの標準だと様々なシステムに拡張が難しいので~~ということらしい。
確かに、今回インストールしているcrdの定義の中に、マニフェストで設定した内容が含まれる。
elasticsearchRefs:
description: |-
ElasticsearchRefs is a reference to a list of Elasticsearch clusters running in the same Kubernetes cluster.
Due to existing limitations, only a single ES cluster is currently supported.
まあそういうことなんだろう。
なお、本来個別でインストールする必要はないそう。(operator側でもインストールしてくれる)
eck-operator
ECK OperatorがElasticsearchやKibanaなどの制御する仕組みのようです。Kubernetesの観点で言えば、OperatorというパターンがあってOperatorからServiceなりPodなりを制御してくれるようです。
eck-stack
ElasticsearchやKibanaなどの設定を定義できる本体です。こいつがeck-operatorからデプロイされるようです。
各コンポーネントの設定はHelmのvaluesとして設定しています。便利ですね。今回はElasticで公開しているExampleを適当に組み合わせて動くようになっただけですが、やりようがわかっただけでも大きいです。
今回、Elasticsearchが3こ、logstashが2ことしてデプロイしています。

この環境で色々実験していきたいと思います。
触ってみる
logstashへいい感じにログを流す
logstashはtcp/5044でjsonを受け取るように設定しています。これに対してデータを送って、ログを取り込みます。
for ((i=0; i<=100000; i++)); do
echo "{\"test\": \"test\", \"num\": $i}" | nc 192.168.2.143 31111;sleep 1;
done

numのところが1ずつ変化して取り込めていますね。logstashのイベント処理数を見てみると、21件ずつ担っているのでうまくロードバランスされています。

※今回はtcpで受け付けているのでkubernetes上の機能でバランシングしています。
Elasticserchを落としてみる
Elasticのノードを一つ落としてみましょう。DeleteしたあとにKibanaからNodeが落ちていることが確認できます。

落ちました。

ですが、Shardがelasticsearch-es-default-1とelasticsearch-es-default-2に分かれているため特段検索に影響はありませんでした。

可観測性
Elastic-stackのObservabilityの機能すごいですね。。初めて知りました。今回はArgoCD経由でインストールしているので、設定ファイルのyamlしか書いてないのにここまでできるとは。。
Podのメモリ使用率

Metrics Explorer

Logs Explorer

Elasticsearch増やしてみる
意味はありませんが、3から6に増やしてみます。設定はすべてgithub上で管理されているため、数字を変えればOKです
ArgoCD側からREFRESHすることで作り始めます。(4個目が作られている)

が、ここでサーバーが限界を迎えてしまいました。残念
細かい設定
ドキュメントに試してみたい設定がいくつかあったのでピックアップしておきます。
最後に
- スケーリングすごい
- Kubernetesむずい