クラウドネイティブの民営化されたPaaSプラットフォームの配信方法

著者:有名なインターネット会社のエキスパートエンジニア、NiuYufu。オープンソースのように/共有したいので、K8とgolangゲートウェイについて詳細に調査してください。

この記事では、クラウドネイティブを使用して民営化配信の問題を解決し、PaaSプラットフォームを構築してビジネスプラットフォームの再利用性を向上させる方法について説明します。トピックに入る前に、2つのキーワードを明確にする必要があります。

  • PaaSプラットフォーム:複数のコアビジネスサービスがプラットフォーム全体としてカプセル化され、プラットフォームの形でサービスを提供します。
  • プライベート配信:プラットフォームはプライベートクラウド環境にデプロイする必要があり、ネットワークがなくても動作できます。

従来の配信の問題点

上に示したように:プライベートクラウドには明確なセキュリティ要件があります

  1. プライベートクラウドサービスは外部ネットワークに接続できず、データは一方向のゲートキーパーを介してのみ内部ネットワーク上のプライベートクラウドに転送できます。
  2. ソースコードは会社のコンピューター室にのみ保存でき、プライベートクラウドはコンパイルされたファイルのみを展開します。
  3. サービスは随時繰り返されますが、サービスの安定性を確保するためには、独立したビジネスモニタリングを構築する必要があります。

上記の要件に基づいて、直面する課題はおそらくいくつかあります。

  1. アーキテクチャの移植性が低い:サービス間の構成は複雑であり、構成ファイルは複数の異種言語用に変更する必要があり、固定サービスDNSはありません。
  2. 導入と運用に高いコストがかかる:サービスに依存する環境ではオフラインインストールをサポートする必要があり、サービスの更新はローカルの運用および保守担当者が手動で完了する必要があります。複雑なシナリオでは、完全な導入に1か月あたり数人かかる場合があります。
  3. 運用と保守の監視に高いコストがかかる:監視はシステムレベル/サービスレベル/ビジネスレベルの監視をサポートする必要があり、通知方法はSMS、Webhook、その他のタイプをサポートする必要があります。

アーキテクチャスキーム

私たちの原則は、クラウドネイティブを採用し、既存の機能を再利用することであり、業界で既存の成熟した技術ソリューションを使用することが可能です。サービスオーケストレーションとしてKubeSphere+K8Sを使用します。セキュリティとシンプルさを考慮して、Syncdの完全なDevOps機能を再開発します。監視システムはNightingale+Prometheusソリューションを使用します。

上に示したアーキテクチャ

  1. 青いボックスは、基盤となるPaaSクラスターです。アーキテクチャの移行が不十分であるという問題を解決するために、サービスのオーケストレーションとビジネスサービスの一般的なサービスのアップグレードを統合しました。
  2. 赤いボックスでは、監視システムがオーケストレーションサービスとして存在し、すべての監視項目が配信前に構成されています。これは、監視システムの高い運用および保守コストの問題を解決するために使用されます。
  3. 紫色のボックスでは、サービスコンテナを自動的にプルして、ネットワークセグメント全体に展開できます。これは、サービスサービスの展開コストが高いという問題を解決するために使用されます。

以下では、これら3つの部分を紹介します。

サービスオーケストレーション:KubeSphere

KubeSphereのビジョンは、K8をコアとするクラウドネイティブ分散オペレーティングシステムを作成することです。マルチクラウドおよびマルチクラスターでのクラウドネイティブアプリケーションの統合された分散と運用および保守管理、およびアクティブなコミュニティもあります。

KubeSphereを選択した理由は次のとおりです。

製品に基づいて独自の民営化された配信ソリューションをカスタマイズします

民営化された画像ファイルのパッケージ

製品リストを作成します。

apiVersion: kubekey.kubesphere.io/v1alpha2
kind: Manifest
metadata:
  name: sample
spec:
  arches:
  - amd64
...
  - type: kubernetes
    version: v1.21.5
  components:
    helm:
      version: v3.6.3
    cni:
      version: v0.9.1
    etcd:
      version: v3.4.13
    containerRuntimes:
    - type: docker
      version: 20.10.8
    crictl:
      version: v1.22.0
    harbor:
      version: v2.4.1
    docker-compose:
      version: v2.2.2
  images:
  - dockerhub.kubekey.local/kubesphere/kube-apiserver:v1.22.1
...

次に、コマンドでエクスポートできます。

$ ./kk artifact export -m manifest-sample.yaml -o kubesphere.tar.gz

プライベート展開

デプロイメントマニフェストを作成します。

apiVersion: kubekey.kubesphere.io/v1alpha2
kind: Cluster
metadata:
  name: sample
spec:
  hosts:
  - {name: kubesphere01.ys, address: 10.89.3.12, internalAddress: 10.89.3.12, user: kubesphere, password: "Kubesphere123"}
  - {name: kubesphere02.ys, address: 10.74.3.25, internalAddress: 10.74.3.25, user: kubesphere, password: "Kubesphere123"}
  - {name: kubesphere03.ys, address: 10.86.3.66, internalAddress: 10.86.3.66, user: kubesphere, password: "Kubesphere123"}
  - {name: kubesphere04.ys, address: 10.86.3.67, internalAddress: 10.86.3.67, user: kubesphere, password: "Kubesphere123"}
  - {name: kubesphere05.ys, address: 10.86.3.11, internalAddress: 10.86.3.11, user: kubesphere, password: "Kubesphere123"}
  roleGroups:
    etcd:
    - kubesphere01.py
    - kubesphere02.py
    - kubesphere03.py
    control-plane:
    - kubesphere01.py
    - kubesphere02.py
    - kubesphere03.py
    worker:
    - kubesphere05.py
    registry:
    - kubesphere04.py
  controlPlaneEndpoint:
    internalLoadbalancer: haproxy
    domain: lb.kubesphere.local
    address: ""
    port: 6443
  kubernetes:
    version: v1.21.5
    clusterName: cluster.local
  network:
    plugin: calico
    kubePodsCIDR: 10.233.64.0/18
    kubeServiceCIDR: 10.233.0.0/18
    multusCNI:
      enabled: false
  registry:
    type: harbor
    auths:
      "dockerhub.kubekey.local":
        username: admin
        password: Kubesphere123
...

インストールと展開を実行します。

$ ./kk create cluster -f config-sample.yaml -a kubesphere.tar.gz --with-packages --with-kubesphere --skip-push-images

多数の複雑なK8sデプロイメント、高可用性ソリューション、ハーバー民営化ミラーウェアハウスなどを自動的にインストールできることが判明しました。これにより、民営化された配信シナリオでのK8sコンポーネントのデプロイが大幅に簡素化されます。

ビジュアルインターフェイスにより、操作プロセスが大幅に簡素化されます

  • デプロイメントの作成:コンテナーサービスのデプロイメント、ストレージ、およびサービスアクセスのパイプライン作成。

  • リソースの制限:コンテナのリソース使用率を制限し、テナントのリソース使用率を制限します。

  • リモートログイン:コンテナリモートログイン機能。

KubeSphereに基づくビジネス展開経験の共有

民営化のシナリオでは、単一インスタンスの障害が全体的な使用に影響を与えないように、高可用性サービスインスタンスのデプロイが構築されます。次の点を確認する必要があります。

1.サービスには固定のネットワークIDとストレージが必要なため、「ステートフルレプリカセットの展開」を作成する必要があります。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  namespace: project
  name: ${env_project_name}
  labels:
    app: ${env_project_name}
spec:
  serviceName: ${env_project_name}
  replicas: 1
  selector:
    matchLabels:
      app: ${env_project_name}
  template:
    metadata:
      labels:
        app: ${env_project_name}
    spec:
      containers:
        - name: ${env_project_name}
          image: ${env_image_path}
          imagePullPolicy: IfNotPresent

2.ステートフルレプリカセットは、ホストの非アフィニティを使用して、サービスが異なるホストに確実に分散されるようにします。

....
affinity:
   podAntiAffinity:
     preferredDuringSchedulingIgnoredDuringExecution:
       - weight: 100
         podAffinityTerm:
           labelSelector:
             matchExpressions:
               - key: app
                 operator: In
                 values:
                   - ${env_project_name}
           topologyKey: kubernetes.io/hostname
....

3.サービス間の相互呼び出しは、K8の基盤となるDNSを使用して構成されます。

4.クラスターが外部リソースに依存している場合は、「サービス」に設定してから、内部でサービスを提供する必要があります。

kind: Endpoints
apiVersion: v1
metadata:
  name: redis-cluster
  namespace: project
subsets:
  - addresses:
      - ip: 10.86.67.11
    ports:
      - port: 6379
---
kind: Service
apiVersion: v1
metadata:
  name: redis-cluster
  namespace: project
spec:
  ports:
    - protocol: TCP
      port: 6379
      targetPort: 6379

5. nip.ioドメイン名を使用して、サービスの動的ドメイン名解決のデバッグを実現します。nip.ioは、要求されたドメイン名に従ってIP情報を自動的に設定して、応答のIP情報マッピングを完了することができます。

$ nslookup abc-service.project.10.86.67.11.nip.io
Server:         169.254.25.10
Address:        169.254.25.10:53

Non-authoritative answer:
Name:   abc-service.project.10.86.67.11.nip.io
Address: 10.86.67.11

したがって、Ingressを構築するときに、このドメイン名を直接使用できます。

---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: gatekeeper
  namespace: project
spec:
  rules:
    - host: gatekeeper.project.10.86.67.11.nip.io
      http:
        paths:
          - path: /
            pathType: ImplementationSpecific
            backend:
              service:
                name: gatekeeper
                port:
                  number: 8000

6.ディレクトリをホストにマウントします。コンテナをホストディレクトリに直接関連付ける必要がある場合があります。具体的な操作は次のとおりです。

...
spec:
    spec:
...
          volumeMounts:
            - name: vol-data
              mountPath: /home/user/data1
      volumes:
        - name: vol-data
          hostPath:
            path: /data0

7.主にStatefulSet、Service、volumeClaimTemplates、Ingressを含む、ワークロードのステートフルデプロイメント。例は次のとおりです。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  namespace: project
  name: gatekeeper
  labels:
    app: gatekeeper
spec:
  serviceName: gatekeeper
  replicas: 1
  selector:
    matchLabels:
      app: gatekeeper
  template:
    metadata:
      labels:
        app: gatekeeper
    spec:
      containers:
        - name: gatekeeper
          image: dockerhub.kubekey.local/project/gatekeeper:v362
          imagePullPolicy: IfNotPresent
          ports:
            - name: http-8000
              containerPort: 8000
              protocol: TCP
            - name: http-8080
              containerPort: 8080
              protocol: TCP
          resources:
            limits:
              cpu: '2'
              memory: 4Gi
          volumeMounts:
            - name: vol-data
              mountPath: /home/user/data1
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                    - key: app
                      operator: In
                      values:
                        - gatekeeper
                topologyKey: kubernetes.io/hostname
  volumeClaimTemplates:
    - metadata:
        name: vol-data
      spec:
        accessModes: [ "ReadWriteOnce" ]
        resources:
          requests:
            storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
  name: gatekeeper
  namespace: project
  labels:
    app: gatekeeper
spec:
  ports:
    - name: "http-8000"
      protocol: TCP
      port: 8000
      targetPort: 8000
    - name: "http-8080"
      protocol: TCP
      port: 8080
      targetPort: 8080
  selector:
    app: gatekeeper
  type: NodePort
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: gatekeeper
  namespace: project
spec:
  rules:
    - host: gatekeeper.project.10.86.67.11.nip.io
      http:
        paths:
          - path: /
            pathType: ImplementationSpecific
            backend:
              service:
                name: gatekeeper
                port:
                  number: 8000
    - host: gatekeeper.project.10.86.68.66.nip.io
      http:
        paths:
          - path: /
            pathType: ImplementationSpecific
            backend:
              service:
                name: gatekeeper
                port:
                  number: 8080

DevOps:Syncdに基づくサービス自動化デリバリーの構築

DevOpsには多くのオプションがありますが、ここではJenkinsやGitRunnerなどを使用しませんが、二次開発にはチームに馴染みのあるSyncdを使用します。2つの理由があります:

  1. セキュリティ上の理由から:ソースコードをローカルに保存できないため、gitlabに基づくソリューションの構築とパッケージ化はあまり役に立ちません。また、それを使用することはリソースの浪費です。
  2. 機能の簡素化:Syncdは2年以上停止されていますが、そのコアCICD機能は比較的完全であり、強力なフロントエンドとバックエンドのスケーラビリティを備えています。対応する機能を簡単に拡張できます。

同期されたコアアイデア:

  1. ローカルツールチェーンを使用してパッケージ化されたイメージを構築することから、dockerpushはここではgitpushとして理解できます。
  2. Syncdを介してイメージパッケージをプルして展開プロセスを完了し、パッケージ化してオンラインにし、パッケージ化時にバージョン番号を設定して、サービスのロールバックを容易にします。

ローカルツールチェーンを構築する

1.プロジェクトに基づいてディレクトリを作成します

#创建目录
cd /Users/niuyufu/goproject/abc-service
mkdir -p devops
cd devops

2. Dockerfileをインポートします。ビジネスに基づいて、自分で作成できます。3.tool.shファイルを作成します

cat >> tool.sh << EOF
#!/bin/sh
 
###########配置区域##############
 
#模块名称,可变更
module=abc-service
#项目名称
project=project1
#容器名称
container_name=${project}"_"${module}
#镜像名称
image_name=${project}"/"${module}
#服务端口映射:宿主机端口:容器端口,多个逗号间隔
port_mapping=8032:8032
#镜像hub地址
image_hub=dockerhub.kubekey.local
#镜像tag
image_tag=latest
 
###########配置区域##############
 
#构建工具
action=$1
case $action in
"docker_push")
  image_path=${image_hub}/${image_name}:${image_tag}
  docker tag ${image_name}:${image_tag} ${image_path}
  docker push ${image_path}
  echo "镜像推送完毕,image_path: "${image_path}
  ;;
"docker_login")
  container_id=$(docker ps -a | grep ${container_name} | awk '{print $1}')
  docker exec -it ${container_id} /bin/sh
  ;;
"docker_stop")
  docker ps -a | grep ${container_name} | awk '{print $1}' | xargs docker stop
  container_id=`docker ps -a | grep ${container_name} | awk '{print $1}' | xargs docker rm`
  if [ "$container_id" != "" ];then
    echo "容器已关闭,container_id: "${container_id}
  fi
 
  if [ "$images_id" != "" ];then
    docker rmi ${images_id}
  fi
 
  ;;
"docker_run")
  docker ps -a | grep ${container_name} | awk '{print $1}' | xargs docker stop
  docker ps -a | grep ${container_name} | awk '{print $1}' | xargs docker rm
  port_mapping_array=(${port_mapping//,/ })
  # shellcheck disable=SC2068
  for var in ${port_mapping_array[@]}; do
    port_mapping_str=${mapping_str}" -p "${var}
  done
  container_id=$(docker run -d ${port_mapping_str} --name=${container_name} ${image_name})
  echo "容器已启动,container_id: "${container_id}
  ;;
"docker_build")
  if [ ! -d "../output" ]; then
    echo "../output 文件夹不存在,请先执行 ../build.sh"
    exit 1
  fi
  cp -rf ../output ./
  docker build -f Dockerfile -t ${image_name} .
  rm -rf ./output
  echo "镜像编译成功,images_name: "${image_name}
  ;;
*)
  echo "可运行命令:
docker_build    镜像编译,依赖../output 文件夹
docker_run      容器启动,依赖 docker_build
docker_login    容器登陆,依赖 docker_run
docker_push     镜像推送,依赖 docker_build"
  exit 1
  ;;
esac
EOF

4.プロジェクトのパッケージ化を実行します。出力が./outputにあることを確認してください

$cd ~/goproject/abc-service/
$sh build.sh
abc-service build ok
make output ok
build done

5.サービスのデバッグにtool.shツールを使用します

tools.shの実行順序は、一般的に次のようになります。./outputoutput→docker_build→docker_run→docker_login→docker_push

$cd devops
$chmod +x tool.sh
#查看可运行命令
$sh tool.sh
可运行命令:
docker_build    镜像编译,依赖../output 文件夹
docker_run      容器启动,依赖 docker_build
docker_login    容器登陆,依赖 docker_run
docker_push     镜像推送,依赖 docker_build
 
 
#docker_build举例:
$sh tool.sh docker_build
[+] Building 1.9s (10/10) FINISHED
 => [internal] load build definition from Dockerfile                                                                                      0.1s
 => => transferring dockerfile: 37B                                                                                                       0.0s
 => [internal] load .dockerignore                                                                                                         0.0s
 => => transferring context: 2B
...                                                                   0.0s
 => exporting to image                                                                                                                    0.0s
 => => exporting layers                                                                                                                   0.0s
 => => writing image sha256:0a1fba79684a1a74fa200b71efb1669116c8dc388053143775aa7514391cdabf                                              0.0s
 => => naming to docker.io/project/abc-service                                                                                         0.0s
 
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
镜像编译成功,images_name: project/abc-service
 
 
#docker_run举例:
$ sh tool.sh docker_run
6720454ce9b6
6720454ce9b6
容器已启动,container_id: e5d7c87fa4de9c091e184d98e98f0a21fd9265c73953af06025282fcef6968a5
 
 
#可以使用 docker_login 登陆容器进行代码调试:
$ sh tool.sh docker_login
sh-4.2# sudo -i
root@e5d7c87fa4de:~$
 
 
#docker_push举例:
$sh tool.sh docker_push                                                                                                              130 ↵
The push refers to repository [dockerhub.kubekey.local/citybrain/gatekeeper]
4f3c543c4f39: Pushed
54c83eb651e3: Pushed
e4df065798ff: Pushed
26f8c87cc369: Pushed
1fcdf9b8f632: Pushed
c02b40d00d6f: Pushed
8d07545b8ecc: Pushed
ccccb24a63f4: Pushed
30fe9c138e8b: Pushed
6ceb20e477f1: Pushed
76fbea184065: Pushed
471cc0093e14: Pushed
616b2700922d: Pushed
c4af1604d3f2: Pushed
latest: digest: sha256:775e7fbabffd5c8a4f6a7c256ab984519ba2f90b1e7ba924a12b704fc07ea7eb size: 3251
镜像推送完毕,image_path: dockerhub.kubekey.local/citybrain/gatekeeper:latest

#最后登陆Harbor测试镜像是否上传
https://dockerhub.kubekey.local/harbor/projects/52/repositories/gatekeeper

Syncdに基づくサービスパッケージングと構築

1.プロジェクト構成

アイテムを追加

tool.shで生成されたミラーアドレスを設定します。

ビルドスクリプトを設定します。

ステートフルワークロードを参照してビルドスクリプトに入力します。

2.オンライン注文を作成します

3.デプロイメントを実行するためのデプロイメントパッケージをビルドします

4. KubeSphereに切り替えて、展開効果を確認します。

これまでのところ、DevOpsとKubeSphereの機能は接続されています。

サービス監視:ナイチンゲールに基づくエンタープライズレベルの監視の構築

選択の理由

  1. Visualization Engine:組み込みのテンプレート。すぐに使用できます。

  1. アラーム分析エンジン:柔軟な管理、アラームの自己修復、およびすぐに使用できる。

  1. Helm Chartをサポートして、ワンクリックでアプリケーションとサービスのデプロイを完了します。民営化のシナリオでは、コンテナー統合のローカリゼーションのみを考慮する必要があります。
$ git clone https://github.com/flashcatcloud/n9e-helm.git
$ helm install nightingale ./n9e-helm -n n9e --create-namespace

実際のルール構成デモ

  1. アラームルールを設定し、PromQLをシームレスにサポートして、さまざまなルールを柔軟に記述します。

  1. アラーム受信グループの設定

  1. アラームメッセージとリカバリメッセージの実際の受信

要約する

民営化の提供では、ビジネスシナリオが異なるため、クラウドネイティブアプリケーションの選択も異なります。この記事では、私たち自身のビジネスシナリオのみを紹介します。ご不明な点がございましたら、訂正してください。また、他のシナリオのクラウドネイティブアプリケーションについても、いつでもご相談ください。

この記事は、複数投稿のブログプラットフォームであるOpenWriteによって公開されています。

{{o.name}}
{{m.name}}

おすすめ

転載: my.oschina.net/u/4197945/blog/5556886