birabiraのめも

忘れっぽいのでここにメモをしていきます

Kubernetes(Kind)を使ってArgoCDからECK(Elastic Cloud on Kubernetes)デプロイしてみる

はじめに

少し前からKuberenetes入門しなければという使命感はあったものの、日常が忙しくどうしても入門できていなかったがやっと入門したので記録として残していきたいと思う。

今回は、KubernetesをDockerコンテナとして構築できるKindというツールを使って構築し、ArgoCDを使ってGithub上にあるリポジトリから構成を読んでECKをデプロイします。

いわゆるGitOpsでやっていきたい。

先週入門したばっかりなので、説明が間違っていたり設定が足りない部分があるかと思うがそこはご容赦いただきたい。

今回とりあえず構築まではできたので、Kuberenetesのスケーラビリティとか色々体感したい~。

Kind

説明は公式を読んでもらったほうが早いと思うので。

kind.sigs.k8s.io

ArgoCD

Kubernetesで動かすことで、Gitのリポジトリ上に保存しているマニフェストファイルを監視して、変更があればKuberenetesにデプロイすることができる。すごい。

↓詳細はこちらを読んでもらったほうがいいと思う

tech-lab.sios.jp

ECK

Kubernetes上で動かすように構成されたElasticsearchとKibana。まだテクニカルプレビューであるものの、BeatsやFleetなども対応している。

基本的には、Kubernetesマニフェストファイルをデプロイすることができるが、パッケージマネージャーであるHelmでのデプロイにも対応している。

↓公式サイト

www.elastic.co

Github

github.com

構築

早速構築していきます。

  • 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

kubernetes.io

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

kind.sigs.k8s.io

コマンドが打てれば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台に分けられるものを、コンテナとして作ってるっぽい。

kubernetes.io

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リポジトリの中を参照して、おいてあるマニフェストファイルをベースに構築をします。どのようなファイルが置いてあるのか、確認して行きたいと思います。

github.com

eck-operator-crds

github.com

まずは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

github.com

ECK OperatorがElasticsearchやKibanaなどの制御する仕組みのようです。Kubernetesの観点で言えば、OperatorというパターンがあってOperatorからServiceなりPodなりを制御してくれるようです。

eck-stack

ElasticsearchやKibanaなどの設定を定義できる本体です。こいつがeck-operatorからデプロイされるようです。

コンポーネントの設定はHelmのvaluesとして設定しています。便利ですね。今回はElasticで公開しているExampleを適当に組み合わせて動くようになっただけですが、やりようがわかっただけでも大きいです。

github.com

今回、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です

github.com

ArgoCD側からREFRESHすることで作り始めます。(4個目が作られている)

が、ここでサーバーが限界を迎えてしまいました。残念

細かい設定

ドキュメントに試してみたい設定がいくつかあったのでピックアップしておきます。

www.elastic.co

www.elastic.co

www.elastic.co

最後に