手把手带你玩转iceberg-开源节流spend_wis

上一篇 “手把手带你玩转iceberg-trino on k8s” 结束后,当前我们的工程大概是这样的。

image.png

我也是非工作时间玩玩,虽然我通过停用按量计费的ECS减少开支,但即使这样大概一个小时还要花费3毛2,一周不碰就要白白花费50块钱。有什么办法可以省下这个钱呢?本文就要过日子。

只有每次用完把集群和ECS都释放掉了,那就要想办法能够在用的时候迅速的把集群构建起来。当然每次构建集群在阿里云上申请ECS和K8s集群的步骤是少不了的,但是操作熟练了也就五分钟的事情。
关键的是如何把应用部署起来。这个时候就想到用gitops了。我的代码已经放到gitee上了,用gitOPS就可以完成一键部署。

这里会遇到几个问题:

  1. gitOPS我使用我熟悉的ArgoCD,但是ArgoCD也要安装到k8s集群中的。这个我们可以通过在小A上执行脚本的方式搞定。
  2. 然后就是k8s集群里的Argo CD需要访问外网的gitee,我们就需要配置SNAT,保证K8S集群也能正常访问外网
  3. 当前我们的minio-server还启动在小A上,既然都gitOPS,我们直接把它移到集群里吧。小A上的nginx添加一个后台,也就搞定了web页面查看obs桶数据的需求。

改造后demo架构图:

image.png

代码仓库地址

gitee.com/nativesailo…

minio-server入集群

集群中安装minio

参考:

blog.csdn.net/qq_18671415…

github.com/kubernetes/…

创建namespace

kubectl create namespace minio
复制代码

创建pvc

minio-standalone-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: minio-pv-claim
spec:
  storageClassName: pure-block
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
复制代码

配置deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: minio-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: minio
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: minio
    spec:
      volumes:
      - name: storage
        persistentVolumeClaim:
          claimName: minio-pv-claim
      containers:
      - name: minio
        image: registry-vpc.cn-zhangjiakou.aliyuncs.com/sailor-datalake/minio:latest
        command:
        - /bin/sh
        - -c
        - minio server --console-address ":9090" /storage
        args:
        - server
        - /storage
        env:
        - name: MINIO_ACCESS_KEY
          value: "minioadmin"
        - name: MINIO_SECRET_KEY
          value: "minioadmin"
        ports:
        - name: data
          containerPort: 9000
          protocol: "TCP"
        - name: console
          containerPort: 9090
          protocol: "TCP"
        volumeMounts:
        - name: storage
          mountPath: "/storage"
复制代码

配置service

minio-standalone-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: minio
spec:
  type: NodePort
  ports:
    - name: api
      port: 9000
      targetPort: 9000
      nodePort: 32002
      protocol: TCP
    - name: console
      port: 9090
      targetPort: 9090
      nodePort: 32003
      protocol: TCP
  selector:
    app: minio
复制代码

配置小A上的nginx

cd /usr/local/nginx/conf
vim nginx.conf


    server {
          listen       32003;
          server_name  localhost;
          location / {
               proxy_read_timeout      300;
               proxy_connect_timeout   300;
               proxy_redirect          off;
               proxy_set_header    Host                $http_host;
               proxy_set_header    X-Real-IP           $remote_addr;
               proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
               proxy_set_header    X-Forwarded-Proto   $scheme;
               proxy_set_header    X-Frame-Options     SAMEORIGIN;
               proxy_pass http://172.28.166.135:32003;
          }
          error_page   500 502 503 504  /50x.html;
          location = /50x.html {
            root   /usr/share/nginx/html;
          }
    }
复制代码

nginx 更改配置文件后需要重启生效

  • /usr/local/nginx/sbin/nginx -t 测试配置文件修改是否正常

  • /usr/local/nginx/sbin/nginx -s reload 重新加载

web访问

image.png

后期规划将minio-server搞成集群模式

参考:
github.com/kubernetes/…
blog.csdn.net/moon_naxx/a…

配置 SNAT

参考:
阿里云ECS主机自建SNAT,实现没有公网的主机通过有公网的主机访问外网。
blog.csdn.net/weixin_4638…

记录一下一些iptables的命令。

iptables -t nat -A POSTROUTING -s 172.16.0.0/12 -j SNAT --to-source 172.28.166.95

iptables -t nat  -L -n

iptables -t nat -L -n --line-numbers

iptables -t nat -D POSTROUTING 1
复制代码

部署Argo CD到集群

Argo CD是用于Kubernetes的声明性GitOps连续交付工具。

argoCD服务端安装

kubectl create namespace argocd

kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
复制代码

argoCD客户端安装

curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64 

chmod +x /usr/local/bin/argocd
复制代码

安装太慢或失败使用下面的方法

wget https://stob-tools.obs.cn-north-4.myhuaweicloud.com/argocd-util-linux-amd64

cp argocd-util-linux-amd64 /usr/local/sbin/argocd

chmod 755 /usr/local/sbin/argocd

vi /etc/profile
在文件末尾添加:export PATH="$PATH:/usr/local/sbin"

复制代码

获取密码和修改密码

网上好多文章比较老,默认密码是admin和argocd-server的pod的名字。
我一直登录不上,提示“rpc error: code = Unauthenticated desc = Invalid username or password”,郁闷了好久,直到发现了下面这篇文章。

blog.csdn.net/weixin_4183…

开始,小A上进行操作

  1. 暴露端口供访问
kubectl port-forward --address 0.0.0.0 svc/argocd-server -n argocd 8084:443 &
复制代码

TODO:Ingress的访问方式,参考argo-cd.readthedocs.io/en/stable/o…

  1. 访问8084端口 
小A的外网IP:8084
复制代码

image.png

  1. 获取密码
kubectl get secret -n argocd argocd-initial-admin-secret -o yaml

echo cFN4SG5kR0tadFpjQ3Jaag== |base64 -d
复制代码

一次输出

kubectl \
    --namespace argocd \
    get secret argocd-initial-admin-secret \
    --output jsonpath="{.data.password}" \
    | base64 --decode
复制代码
  1. 修改密码
argocd login localhost:8084
输入admin和上面获取的密码

argocd account update-password \
   --account admin \
   --current-password Xpd1to6SzE6MdoqZ \
   --new-password Happy_123
复制代码

改造工程,支持Argo CD部署

Argo CD支持的部署方式有kustomize应用程序和helm chat等多种方式,这里我们选用kustomize,改动小,理解容易。

参考:

kustomize压缩包下载

www.jianshu.com/p/65490ab65…
github.com/kubernetes-…

kustomize使用

kubernetes.io/zh/docs/tas…
zhuanlan.zhihu.com/p/92153378
blog.csdn.net/weixin_3051…

具体配置直接参考代码仓里的kustomization.yaml文件

├── /kustomization.yaml
	├── maria
		└── kustomization.yaml
	└── minio
		└── kustomization.yaml
	├── nfs
		└── kustomization.yaml
	└── trino-on-k8s
                ├── hive_metastore
                        └── kustomization.yaml
                ├── trino
                        └── kustomization.yaml
复制代码

cli配置

因为后面我需要在小A上通过shell脚本的方式初始化整个Argo配置,所以我们这边主要研究通过cli客户端进行各种argoCD的配置,web页面只用来观察集群中应用的运行状态。

参考: blog.csdn.net/weixin_4004…

配置集群

  1. 列出当前 kubeconfig 中的所有集群上下文:
[root@iZ8vbgn00yu75o270lb2azZ ~]# kubectl config get-contexts -o name
kubernetes-admin-c279f0a9073e2406db3baf658f3574da2
复制代码
  1. argoCD添加集群信息
[root@iZ8vbgn00yu75o270lb2azZ ~]# argocd cluster add kubernetes-admin-c279f0a9073e2406db3baf658f3574da2
INFO[0000] ServiceAccount "argocd-manager" created in namespace "kube-system" 
INFO[0000] ClusterRole "argocd-manager-role" created    
INFO[0000] ClusterRoleBinding "argocd-manager-role-binding" created 
Cluster 'https://172.28.166.156:6443' added
复制代码

上述命令会将 ServiceAccount (argocd-manager) 安装到该 kubectl 上下文的 kube-system 命名空间中,并将 ServiceAccount 绑定到管理员级别的 ClusterRole,Argo CD 使用此 ServiceAccount 令牌来执行任务管理(部署/监控)

创建应用

cil命令行创建应用

argocd app create datalake --repo https://gitee.com/nativesailor/iceberg-on-k8s --revision spend_wisely --path . --dest-server https://kubernetes.default.svc --dest-namespace datalake --sync-policy automated
复制代码

或者web页面创建应用

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: datalake
spec:
  destination:
    name: ''
    namespace: datalake
    server: 'https://kubernetes.default.svc'
  source:
    path: .
    repoURL: 'https://gitee.com/nativesailor/iceberg-on-k8s'
    targetRevision: spend_wisely
  project: default
  syncPolicy:
    automated: null
复制代码

查看效果

使用39.103.234.55:8084访问argocd的web页面

使用39.103.234.55:32003访问minio的web页面

使用39.103.234.55:32001访问trino的ui页面

脚本一键搞定

我把前面除了argocd客户端的安装都进行了脚本化,具体参看下面的脚本。

#!/bin/bash
echo "Hello My Cluster !"

#重新加载下小A上的nginx配置
/usr/local/nginx/sbin/nginx -t
/usr/local/nginx/sbin/nginx -s reload

#集群中创建ArgoCD的命名空间
kubectl create namespace argocd

#原理的argocd服务端部署yaml是下面注释掉的install.yaml。
我将镜像都拉取后打上tag推到了镜像仓库,argocdpullifnotpresent.yaml是改造后的yaml文件

#kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl apply -n argocd -f argocdpullifnotpresent.yaml

#一直循环检测,直到argocd部署完成
count=`kubectl get pod -n argocd  | grep -o 'Running' | wc -l`
echo $count;
while [ $count -ne 5 ]
do
  echo "waiting ten second"
  sleep 10s
  count=`kubectl get pod -n argocd  | grep -o 'Running' | wc -l`
  echo $count
done

count=`kubectl get pod -n argocd  | grep -o '1/1' | wc -l`
echo $count;
while [ $count -ne 5 ]
do
  echo "waiting ten second"
  sleep 10s
  count=`kubectl get pod -n argocd  | grep -o '1/1' | wc -l`
  echo $count
done
echo "argocd server is ready"

#部署完成了,还是不放心,再等10s
sleep 10s

#映射小A的8084端口到集群的argocd服务
kubectl port-forward --address 0.0.0.0 svc/argocd-server -n argocd 8084:443 &

# 不放心,再等了10s
sleep 10s

#获取argocd的初始密码后进行修改,改成了Happy_123
PASS=$(kubectl \
    --namespace argocd \
    get secret argocd-initial-admin-secret \
    --output jsonpath="{.data.password}" \
    | base64 --decode)
echo $PASS
#PASS=`echo "Happy_123"`
echo $PASS
argocd_login_results=`argocd login --insecure --username admin --password $PASS --grpc-web localhost:8084 | grep "successfully"`

while [[ !($argocd_login_results =~ "successfully") ]]
do
  echo "argocd login failure"
  echo "waiting ten second"
  sleep 10s
  argocd_login_results=`argocd login --insecure --username admin --password $PASS --grpc-web localhost:8084 | grep "successfully"`
done
echo "argocd login successfully"

argocd account update-password --current-password $PASS --new-password Happy_123

# argocd配置集群
#config cluster
context=`kubectl config get-contexts -o name`
argocd cluster add $context

#创建datalake这业务命名空间后,创建argocd的应用
#apply apps
kubectl create namespace datalake

argocd app create datalake --repo https://gitee.com/nativesailor/iceberg-on-k8s --revision spend_wisely --path . --dest-server https://kubernetes.default.svc --dest-namespace datalake --sync-policy automated

# 小A上通过minio的客户端mc配置host
check_mc_results=`mc config host add docker_minio http://worker1:32002 minioadmin minioadmin --api s3v4 | grep "successfully"`
while [[ !($check_mc_results =~ "successfully") ]]
do
  echo "mc config host add docker_minio failure"
  echo "waiting ten second"
  sleep 10s
  check_mc_results=`mc config host add docker_minio http://worker1:32002 minioadmin minioadmin --api s3v4 | grep "successfully"`
done

echo "mc config host add docker_minio successfully"

# 小A上通过minio的客户端在集群的minio服务器上创建了datalake这个bucket桶
check_mc_results=`mc mb docker_minio/datalake | grep "successfully"`
while [[ !($check_mc_results =~ "successfully") ]]
do
  echo "mc mb docker_minio/datalake failure"
  echo "waiting ten second"
  sleep 10s
  check_mc_results=`mc mb docker_minio/datalake | grep "successfully"`
done

echo "mc mb docker_minio/datalake successfully"

echo "end"
复制代码

脚本编写参考:

gist.github.com/vfarcic/f87…

www.jianshu.com/p/16a8e64e1…

已解决问题

小A上查看镜像失败

[root@iZ8vbgn00yu75o270lb2azZ nfs]# docker image ls
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

解决办法:

[docker@izwtbz ~]# systemctl daemon-reload
复制代码
[docker@izwtbz ~]# sudo service docker restart
复制代码
[docker@izwtbz ~]# sudo service docker status 
复制代码

mariadb概率访问失败

label选择问题

nfs-provider 无法拉取镜像问题

指定的serviceaccount没有权限

注:这个问题比较有意思,可以旁通到不少知识,我另立文章解释

argocd镜像拉取慢

  • 修改argocd部署yaml里的镜像,全部改成本地仓库

  • 镜像拉取规则改成IfNotPresent,这样需要同一个镜像的多个pod部署到同一个node节点的时候就不用拉取两次了。

待解决问题

  1. 如何每次重建后,对接的nfs存储都是与原来的,这样就不用有添加minio的datalake这个bucket了。

总结步骤

我们每次要得到一个iceberg体验的环境,只需要进行下面的三步,一个全新的环境大概一刻钟就能生成了。

  1. 申请worker节点,申请集群
  2. 小A上配置worker节点信息和集群信息
  • 小A配置worker节点信息
    vi /etc/hosts

    172.28.166.160 worker1
    172.28.166.161 worker2
    172.28.166.162 worker3
    复制代码
  • 小A配置集群访问权限

image.png

rm $HOME/.kube/config 
vim $HOME/.kube/config 黏贴,保存。
复制代码
  1. 执行脚本
./init.sh
复制代码

请到代码仓获取最新脚本。

如果暂时不玩iceberg,就直接释放ECS节点和删除集群就行了,完全不需要担心环境没了。简直太省钱了!!!

后期规划

使用ArgoCD快速恢复一套开发环境,简直是学生党的福利,后面我要把这套思路做成一个通用的模板来供大家快速适配自己的云原生小项目。