# JEDI 絕地武士 ## JEDI 功能介紹 * 透過 jedi pod 讓我們可以在這個 pod 對整個 k8s 做操作,並且本身擁有 regisry 功能,可以存放 k8s 所需使用的 image * kadm container 為控制整個 k8s,並且可以 build image * dkreg 為 image registry ## Dockerfile 設計 ``` FROM taiwanese/alpine RUN apk update && apk upgrade && apk add --no-cache nano sudo wget curl \ tree elinks bash shadow procps util-linux git coreutils binutils jq \ findutils grep openssh-server tzdata openrc tzdata fuse-overlayfs podman skopeo buildah k9s openssl && \ apk add s3fs-fuse --no-cache --repository http://dl-3.alpinelinux.org/alpine/edge/community/ --allow-untrusted && \ apk add mailcap --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/main/ --allow-untrusted && \ apk add kubectl --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/community/ --allow-untrusted # 設定時區 COPY system.sh /usr/bin/system.sh COPY secretcreate.sh /home/bigred/bin/secretcreate.sh RUN cp /usr/share/zoneinfo/Asia/Taipei /etc/localtime && \ ssh-keygen -t rsa -P "" -f /etc/ssh/ssh_host_rsa_key && \ echo -e 'Welcome to KAdmin Console' > /etc/motd && \ # 建立管理者帳號 bigred echo -e 'bigred\nbigred' | adduser -s /bin/bash -h /home/bigred -G wheel bigred && \ mkdir /home/bigred/.ssh && chown bigred:wheel /home/bigred/.ssh && \ echo "%wheel ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \ rm /sbin/reboot && rm /usr/bin/killall && echo "Port 22100" >> /etc/ssh/sshd_config && \ mkdir /home/bigred/.kube && \ echo "export PATH=/home/bigred/bin:$PATH" >> /etc/profile && \ echo "source <(kubectl completion bash)" >> /etc/profile && \ echo "source /usr/bin/system.sh" >> /etc/profile && \ curl https://dl.min.io/client/mc/release/linux-amd64/mc --create-dirs -o /home/bigred/bin/mc && \ chmod +x /home/bigred/bin/mc EXPOSE 22100 ENTRYPOINT ["/usr/sbin/sshd"] CMD ["-D"] ``` ## `secretcreate.sh` ``` #!/bin/bash if [[ -z "$1" ]]; then echo "Please enter the namespace name!" && exit 0 else sudo podman login --tls-verify=false -u docker -p $DKREGPW $DKRESVC:5000 &>/dev/null sudo cp /run/containers/0/auth.json /home/bigred/auth.json; sudo chmod 755 /home/bigred/auth.json for ns in $@ do if ! kubectl get ns "$ns" &>/dev/null; then sudo podman logout $DKRESVC:5000 &>/dev/null sudo rm /home/bigred/auth.json echo "$ns namespace not found!" && exit 0 fi if kubectl get secret dkreg -n "$ns" &>/dev/null; then kubectl delete secret dkreg -n "$ns" &>/dev/null kubectl create secret generic dkreg -n "$ns" --from-file=.dockerconfigjson=/home/bigred/auth.json --type=kubernetes.io/dockerconfigjson &>/dev/null kubectl patch serviceaccount default -n "$ns" -p '{"imagePullSecrets": [{"name": "dkreg"}]}' &>/dev/null echo "$ns namespace imagePullSecrets is change!" else kubectl create secret generic dkreg -n "$ns" --from-file=.dockerconfigjson=/home/bigred/auth.json --type=kubernetes.io/dockerconfigjson &>/dev/null kubectl patch serviceaccount default -n "$ns" -p '{"imagePullSecrets": [{"name": "dkreg"}]}' &>/dev/null echo "$ns namespace imagePullSecrets ok!" fi done sudo podman logout $DKRESVC:5000 &>/dev/null sudo rm /home/bigred/auth.json fi ``` ## `system.sh` 腳本 ``` $ cat /usr/bin/system.sh export POD_NAMESPACE=default export KUBERNETES_SERVICE_PORT=443 export KUBERNETES_SERVICE_HOST=kubernetes.default export KUBERNETES_SERVICE_PORT_HTTPS=443 export JEDIPODNAME=$(kubectl -n kube-system get po | grep jedi | cut -d ' ' -f1) export DKRESVC=$(kubectl -n kube-system get svc jedi | tail -n 1 | tr -s \ - | cut -d ' ' -f3) export DKREGPW=$(kubectl -n kube-system logs $JEDIPODNAME -c dkreg| grep 'user=docker' | cut -d '=' -f6 | cut -d ' ' -f1 | tr -d '"') alias kg='kubectl get' alias ka='kubectl apply' alias kd='kubectl delete' alias kt='kubectl top' alias ks='kubectl get all -n kube-system' alias kt='kubectl top' alias kk='kubectl krew' alias k='kubectl' export PS1='\u@\h:\w$ ' alias pingdup='sudo arping -D -I eth0 -c 2 ' alias ping='ping -c 4' alias dir='ls -alh' alias docker='sudo /usr/bin/podman' echo 'bigred:100000:65535' | sudo tee /etc/subuid &>/dev/null echo 'bigred:100000:65535' | sudo tee /etc/subgid &>/dev/null if [ "$USER" == "bigred" ]; then kubectl get secret 2>/dev/null | grep dkreg &>/dev/null if [ "$?" != "0" ]; then sudo podman login --tls-verify=false -u docker -p $DKREGPW $DKRESVC:5000 &>/dev/null sudo cp /run/containers/0/auth.json /home/bigred/auth.json; sudo chmod 755 /home/bigred/auth.json kubectl create secret generic dkreg -n default --from-file=.dockerconfigjson=/home/bigred/auth.json --type=kubernetes.io/dockerconfigjson &>/dev/null kubectl create secret generic dkreg -n kube-public --from-file=.dockerconfigjson=/home/bigred/auth.json --type=kubernetes.io/dockerconfigjson &>/dev/null echo "dkreg secret ok (namespace: default, kube-public)" kubectl patch serviceaccount default -n default -p '{"imagePullSecrets": [{"name": "dkreg"}]}' &>/dev/null kubectl patch serviceaccount default -n kube-public -p '{"imagePullSecrets": [{"name": "dkreg"}]}' &>/dev/null echo "imagePullSecrets ok (namespace: default, kube-public)" sudo podman logout $DKRESVC:5000 &>/dev/null sudo rm /home/bigred/auth.json else sudo podman login --tls-verify=false -u docker -p $DKREGPW $DKRESVC:5000 &>/dev/null sudo cp /run/containers/0/auth.json /home/bigred/auth.json; sudo chmod 755 /home/bigred/auth.json for ns in default kube-public do old=$(kubectl -n $ns get secret dkreg -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d) new=$(sudo cat /run/containers/0/auth.json) if [[ "$old" != "$new" ]]; then kubectl delete secret dkreg -n "$ns" &>/dev/null kubectl patch serviceaccount default -n "$ns" -p '{"imagePullSecrets": [{"name": "dkreg"}]}' &>/dev/null echo "imagePullSecrets is change (namespace: $ns)" else echo "imagePullSecrets is ok (namespace: $ns)" fi done sudo podman logout $DKRESVC:5000 &>/dev/null sudo rm /home/bigred/auth.json fi if [[ ! -d ~/.krew ]]; then curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/download/v0.4.4/krew-linux_amd64.tar.gz" &>/dev/null tar zxvf krew-linux_amd64.tar.gz &>/dev/null ./krew-linux_amd64 install krew &>/dev/null rm krew-linux_amd64.tar.gz krew-linux_amd64 LICENSE &>/dev/null fi kubectl get pod --field-selector=status.phase==Succeeded -A 2>/dev/null | grep Completed &>/dev/null if [ "$?" == "0" ]; then kubectl delete pod --field-selector=status.phase==Succeeded -A &>/dev/null [ "$?" == "0" ] && echo "delete all completed pods" kubectl delete pod --field-selector=status.phase==Failed -A &>/dev/null [ "$?" == "0" ] && echo "delete all errored pods" echo "" fi fi ``` ## 部屬 * 產生 ssh key 憑證 ``` $ ssh-keygen -t rsa -P "" $ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys ``` ``` $ cd ~;kubectl -n kube-system create secret generic kadm-sshkey --from-file=.ssh/authorized_keys ``` ``` $ kubectl -n kube-system get secret kadm-sshkey NAME TYPE DATA AGE kadm-sshkey Opaque 1 42s ``` * clusterIP、nodeName 需根據自己的 podCIDR 與主機名做變更 * jedi 必須建立在 kube-system namespace * 使用 deployment 方式建立 * 透過 ClusterRole 賦予這個 pod 有最高權限 ``` # roleRef 為引用哪一個 serviceaccount 的權限 # subjects 將權限綁定到指定 serviceaccount $ echo 'apiVersion: v1 kind: ServiceAccount metadata: name: kube-kadm namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: kube-kadm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: kube-kadm namespace: kube-system --- apiVersion: apps/v1 kind: Deployment metadata: name: jedi namespace: kube-system labels: app: jedi spec: replicas: 1 selector: matchLabels: app: jedi template: metadata: labels: app: jedi spec: volumes: - name: kadm-storage hostPath: path: /opt - name: ssh-volume secret: secretName: kadm-sshkey - name: dkreg-storage hostPath: path: /opt/dkreg serviceAccountName: kube-kadm initContainers: - name: init-myservice image: taiwanese/jedi imagePullPolicy: IfNotPresent volumeMounts: - mountPath: "/opt" name: kadm-storage command: - /bin/sh - -c - | if [[ -f /opt/dkreg/htpasswd ]]; then sudo rm /opt/dkreg/htpasswd fi containers: - name: kadm image: taiwanese/jedi imagePullPolicy: IfNotPresent ports: - containerPort: 22100 volumeMounts: - name: kadm-storage mountPath: /opt - name: ssh-volume mountPath: "/etc/sshkey" securityContext: privileged: true lifecycle: postStart: exec: command: - /bin/sh - -c - | cp /etc/sshkey/authorized_keys /home/bigred/.ssh/authorized_keys - image: registry:2 name: dkreg ports: - containerPort: 5000 hostPort: 5000 volumeMounts: - mountPath: "/var/lib/registry" name: dkreg-storage env: - name: REGISTRY_AUTH value: "htpasswd" - name: REGISTRY_AUTH_HTPASSWD_PATH value: "/var/lib/registry/htpasswd" - name: REGISTRY_AUTH_HTPASSWD_REALM value: "Registry Realm" - name: REGISTRY_STORAGE_DELETE_ENABLED value: "true" nodeName: w1 # change --- apiVersion: v1 kind: Service metadata: labels: app: jedi name: jedi namespace: kube-system spec: clusterIP: 10.21.0.11 # change ports: - name: dkregistry port: 5000 protocol: TCP targetPort: 5000 - name: kadm port: 22100 protocol: TCP targetPort: 22100 selector: app: jedi type: ClusterIP' | kubectl apply -f - ``` ## 登入 kadm * 使用 ssh 方式登入 ``` $ ssh bigred@10.21.0.11 -p 22100 Welcome to KAdmin Console dkreg secret ok (namespace: default, kube-public) imagePullSecrets ok (namespace: default, kube-public) Install mc command MinIO mc ok Install krew command kubectl krew ok bigred@jedi-5bb596699d-b6vc8:~$ kubectl get no NAME STATUS ROLES AGE VERSION m1 Ready control-plane,etcd,master,worker 101d v1.26.8+rke2r1 w1 Ready worker 92d v1.26.8+rke2r1 # 也可以 pull image 與 image 製作 bigred@jedi-5bb596699d-b6vc8:~$ sudo podman pull nginx Resolving "nginx" using unqualified-search registries (/etc/containers/registries.conf) Trying to pull docker.io/library/nginx:latest... ```