k8s springcloud apollo

springcloud + apollo的微服務化部署

創建namespace

建立屬于微服務體系下的namespace,cloud.yml

apiVersion: v1
kind: Namespace
metadata:
  name: springcloud

執行 kubectl apply -f cloud.yml

eureka

由于eureka是有狀態的服務,因此采用statefulset部署

  1. 首先創建鏡像,編寫DOCKFILE
FROM java:8
copy ./www /data/www
entrypoint java ${JVM:=-Xms1024m -Xmx1024m} -Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF8 -jar /data/www/iggreport-registry-2.1.5.RELEASE.jar ${APP_OPT}

執行docker build -t eureka:v1 .

  1. 創建eureka.yml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
  namespace: springcloud
type: Opaque
data:
  password: WDhHbkdYcVdGUlg5V3Z3ZQ== 

---
apiVersion: v1
kind: Service
metadata:
  name: eureka
  namespace: springcloud
  labels:
    app: eureka
spec:
  clusterIP: None
  ports:
    - port: 8761
      targetPort: 8761
  selector:
    app: eureka

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: eureka-set
  namespace: springcloud
spec:
  serviceName: eureka
  replicas: 2
  selector:
    matchLabels:
      app: eureka
  template:
    metadata:
      labels:
        app: eureka
    spec:
      terminationGracePeriodSeconds: 10
      containers:
        - name: eureka
          image: eureka:v4
          ports:
          - containerPort: 8761
          env:
            - name: APP_NAME
              value: "eureka"
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: SPRING_APPLICATION_NAME
              value: "igg-report-registry" 
            - name: PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysecret
                  key: password
            - name: APP_OPT
              value: "
                     --eureka.instance.hostname=${POD_NAME}.${APP_NAME}
                     --registerWithEureka=true
                     --fetchRegistry=true
                     --eureka.instance.preferIpAddress=false
                     --eureka.client.serviceUrl.defaultZone=http://${SPRING_APPLICATION_NAME}:${PASSWORD}@eureka-set-0.${APP_NAME}:8761/eureka/,http://${SPRING_APPLICATION_NAME}:${PASSWORD}@eureka-set-1.${APP_NAME}:8761/eureka/
                     "

由于我的注冊中心有做安全校驗,因此配置注冊中心的時候需要填寫密碼,而密碼不想明文寫入到配置的話需要自己加密下,加密方法如下:

[root@master eureka]# echo -n 'X8GnGXqWFRX9Wvwe' | base64
WDhHbkdYcVdGUlg5V3Z3ZQ==

"WDhHbkdYcVdGUlg5V3Z3ZQ=="這個就是經過base64加密后的密碼了。
StatefulSet 作為 Controller 為 Pod 提供唯一的標識。它可以保證部署和 scale 的順序。
StatefulSet是為了解決有狀態服務的問題(對應Deployments和ReplicaSets是為無狀態服務而設計),其應用場景包括:

  • 穩定的持久化存儲,即Pod重新調度后還是能訪問到相同的持久化數據,基于PVC來實現
  • 穩定的網絡標志,即Pod重新調度后其PodName和HostName不變,基于Headless Service(即沒有Cluster IP的Service)來實現
  • 有序部署,有序擴展,即Pod是有順序的,在部署或者擴展的時候要依據定義的順序依次依次進行(即從0到N-1,在下一個Pod運行之前所有之前的Pod必須都是Running和Ready狀態),基于init containers來實現
  • 有序收縮,有序刪除(即從N-1到0)
    從上面的應用場景可以發現,StatefulSet由以下幾個部分組成:
  • 用于定義網絡標志(DNS domain)的Headless Service
  • 用于創建PersistentVolumes的volumeClaimTemplates
  • 定義具體應用的StatefulSet
    StatefulSet中每個Pod的DNS格式為statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local,其中
  • serviceName為Headless Service的名字
  • 0..N-1為Pod所在的序號,從0開始到N-1
  • statefulSetName為StatefulSet的名字
  • namespace為服務所在的namespace,Headless Servic和StatefulSet必須在相同的namespace
  • .cluster.local為Cluster Domain

apollo配置中心

由于apollo配置中心需要mysql數據庫的支持,而mysql不是部署在k8s集群內,因此需要建立一個service可以代理到外部服務去
endpoints.yml

kind: Service
apiVersion: v1
metadata:
  name: my-service
  namespace: springcloud
spec:
  clusterIP: 192.168.186.163
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306

---
kind: Endpoints
apiVersion: v1
metadata:
  name: my-service
  namespace: springcloud
subsets:
  - addresses:
      - ip: 10.0.3.166
    ports:
      - port: 3306

這樣通過訪問這個serviceIp的3306就能訪問到外部節點的mysql

apollo-config部署

先自建apollo-config的鏡像

FROM java:8
COPY www /data/www
entrypoint java ${JVM:=-Xms1024m -Xmx1024m} -Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF8 -jar /data/www/apollo-configservice-1.5.1.jar ${APP_OPT}

apollo-config.yml

apiVersion: v1
kind: Secret
metadata:
  name: apollo-config
  namespace: springcloud
type: Opaque
data:
  password: QXF1YXl3RGJDYVNoeEczbA== 

---
apiVersion: v1
kind: Service
metadata:
  name: apollo-config
  namespace: springcloud
  labels:
    app: apollo-config
spec:
  ports:
    - port: 8888
      targetPort: 8888
  selector:
    app: apollo-config

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apollo-config
  namespace: springcloud
spec:
  replicas: 1
  selector:
    matchLabels:
      app: apollo-config
  template:
    metadata:
      labels:
        app: apollo-config
    spec:
      terminationGracePeriodSeconds: 10
      containers:
        - name: apollo-config
          image: apollo-config:v4
          ports:
          - containerPort: 8888
          env:
            - name: SPRING_APPLICATION_NAME
              value: "apollo-configservice" 
            - name: PASSWORD
              valueFrom:
                secretKeyRef:
                  name: apollo-config
                  key: password
            - name: APP_OPT
              value: "
                     --eureka.instance.hostname=apollo-config
                     --registerWithEureka=true
                     --fetchRegistry=true
                     --eureka.instance.preferIpAddress=false
                     --spring.datasource.url=jdbc:mysql://my-service:3306/apollo_config?useSSL=false&characterEncoding=utf-8
                     --eureka.client.serviceUrl.defaultZone=http://${SPRING_APPLICATION_NAME}:${PASSWORD}@eureka-set-0:8761/eureka/,http://${SPRING_APPLICATION_NAME}:${PASSWORD}@eureka-set-1:8761/eureka/
                     "

apollo-admin部署

自建apollo-admin鏡像

FROM java:8
copy ./www /data/www
entrypoint java ${JVM:=-Xms1024m -Xmx1024m} -Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF8 -jar /data/www/apollo-adminservice-1.5.1.jar ${APP_OPT}

apollo-admin.yml

apiVersion: v1
kind: Secret
metadata:
  name: apollo-admin
  namespace: springcloud
type: Opaque
data:
  password: QXF1YXl3RGJDYVNoeEczbA== 

---
apiVersion: v1
kind: Service
metadata:
  name: apollo-admin
  namespace: springcloud
  labels:
    app: apollo-admin
spec:
  ports:
    - port: 8070
      targetPort: 8070
  selector:
    app: apollo-admin

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apollo-admin
  namespace: springcloud
spec:
  replicas: 1
  selector:
    matchLabels:
      app: apollo-admin
  template:
    metadata:
      labels:
        app: apollo-admin
    spec:
      terminationGracePeriodSeconds: 10
      containers:
        - name: apollo-admin
          image: apollo-admin:v1
          ports:
          - containerPort: 8070
          env:
            - name: APP_NAME
              value: apollo-admin
            - name: SPRING_APPLICATION_NAME
              value: "apollo-adminservice" 
            - name: PASSWORD
              valueFrom:
                secretKeyRef:
                  name: apollo-admin
                  key: password
            - name: APP_OPT
              value: "
                     --eureka.instance.hostname=${APP_NAME}
                     --registerWithEureka=true
                     --fetchRegistry=true
                     --spring.datasource.url=jdbc:mysql://my-service:3306/apollo_config?useSSL=false&characterEncoding=utf-8
                     --eureka.instance.preferIpAddress=false
                     --eureka.client.serviceUrl.defaultZone=http://${SPRING_APPLICATION_NAME}:${PASSWORD}@eureka-set-0.${APP_NAME}:8761/eureka/,http://${SPRING_APPLICATION_NAME}:${PASSWORD}@eureka-set-1.${APP_NAME}:8761/eureka/
                     "

apollo-portal部署

自建apollo-portal鏡像

FROM java:8
copy ./www /data/www
entrypoint java ${JVM:=-Xms1024m -Xmx1024m} -Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF8 -jar /data/www/apollo-portal-1.5.1.jar

apollo-portal.yml

apiVersion: v1
kind: Service
metadata:
  name: apollo-portal
  namespace: springcloud
  labels:
    app: apollo-portal
spec:
  ports:
    - port: 8060
      targetPort: 8060
  selector:
    app: apollo-portal

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apollo-portal
  namespace: springcloud
spec:
  replicas: 1
  selector:
    matchLabels:
      app: apollo-portal
  template:
    metadata:
      labels:
        app: apollo-portal
    spec:
      terminationGracePeriodSeconds: 10
      containers:
        - name: apollo-portal
          image: apollo-portal:v1
          ports:
          - containerPort: 8060

由于apollo-portal需要web頁面對外訪問,因此需要使用ingress配合service,將其對外訪問

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-test
  namespace: springcloud
spec:
  rules:
    #定義域名
    - host: apollo.ingress.com
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: apollo-portal
              port:
                number: 8060

api-common部署

api-common有使用到apollo的配置中心
所以配置文件如下:

app:
  id: iggreport-api-common
apollo:
  meta: http://apollo-config:8888
  bootstrap:
    enabled: true
    namespaces: application,application.yml

構建鏡像Dockerfile

FROM java:8
copy ./www /data/www
entrypoint java ${JVM:=-Xms1024m -Xmx1024m} -Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF8 -jar /data/www/iggreport-api-common-2.1.4.RELEASE.jar ${APP_OPT}

api.yml

apiVersion: v1
kind: Service
metadata:
  name: api-common-service
  namespace: springcloud
  labels:
    app: api-common-service
spec:
  ports:
    - port: 8090
      targetPort: 8090
  selector:
    app: api-common
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-common
  namespace: springcloud
spec:
  replicas: 2
  selector:
    matchLabels:
      app: api-common
  template:
    metadata:
      labels:
        app: api-common
    spec:
      terminationGracePeriodSeconds: 10
      containers:
        - name: api-common
          image: api:v1
          ports:
          - containerPort: 8090
          env:
            - name: APP_NAME
              value: api-common-service
            - name: APP_OPT
              value: "
                     --eureka.instance.hostname=${APP_NAME}  #這里記得要用service的名字,否則網關使用此hostname無法訪問
                     "

gateway部署

由于網關需要redis,因此也需要建個service代理到外部服務的redis集群
endpoint.yml

kind: Service
apiVersion: v1
metadata:
  name: redis-service
  namespace: springcloud
spec:
  ports:
    - protocol: TCP
      port: 7000
      targetPort: 7000

---
kind: Endpoints
apiVersion: v1
metadata:
  name: redis-service
  namespace: springcloud
subsets:
  - addresses:
      - ip: 10.0.3.163
      - ip: 10.0.3.164
      - ip: 10.0.3.165
    ports:
      - port: 7000

自建鏡像

FROM java:8
copy ./www /data/www
entrypoint java ${JVM:=-Xms1024m -Xmx1024m} -Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF8 -jar /data/www/iggreport-gateway-2.2.0.RELEASE.jar ${APP_OPT}

gateway.yml

apiVersion: v1
kind: Service
metadata:
  name: gateway-service
  namespace: springcloud
  labels:
    app: gateway-service
spec:
  ports:
    - port: 8080
      targetPort: 8080
  selector:
    app: gateway
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gateway
  namespace: springcloud
spec:
  replicas: 2
  selector:
    matchLabels:
      app: gateway
  template:
    metadata:
      labels:
        app: gateway
    spec:
      terminationGracePeriodSeconds: 10
      containers:
        - name: gateway
          image: gateway:v1
          ports:
          - containerPort: 8080

然后由于gateway需要對外,因此也需要加入到ingress管理

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-test
  namespace: springcloud
spec:
  rules:
    #定義域名
    - host: gateway.ingress.com
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: gateway-service
              port:
                number: 8080

這樣一個完整的springcloud + apollo的統一配置中心就基于k8s搭建完畢

[root@master k8s]# kubectl get po -o wide -n springcloud
NAME                             READY   STATUS    RESTARTS   AGE    IP           NODE   NOMINATED NODE   READINESS GATES
api-common-5c59b9b649-4rkrm      1/1     Running   0          116m   10.10.2.93   cdh2   <none>           <none>
api-common-5c59b9b649-swpq8      1/1     Running   0          116m   10.10.1.88   cdh3   <none>           <none>
apollo-admin-6dfcf44f8b-flwtc    1/1     Running   0          25h    10.10.2.83   cdh2   <none>           <none>
apollo-config-5d7bddf55c-cn4ph   1/1     Running   0          24h    10.10.2.90   cdh2   <none>           <none>
apollo-portal-bb7d4685d-srw2r    1/1     Running   0          24h    10.10.2.92   cdh2   <none>           <none>
eureka-set-0                     1/1     Running   0          24h    10.10.2.91   cdh2   <none>           <none>
eureka-set-1                     1/1     Running   0          24h    10.10.1.87   cdh3   <none>           <none>
gateway-949d4f958-4ft8x          1/1     Running   0          9m7s   10.10.1.89   cdh3   <none>           <none>
gateway-949d4f958-b4wc7          1/1     Running   0          9m7s   10.10.2.94   cdh2   <none>           <none>

[root@master k8s]# kubectl get svc -o wide -n springcloud
NAME                 TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)    AGE     SELECTOR
api-common-service   ClusterIP   192.168.144.76    <none>        8090/TCP   116m    app=api-common
apollo-admin         ClusterIP   192.168.118.145   <none>        8070/TCP   25h     app=apollo-admin
apollo-config        ClusterIP   192.168.134.51    <none>        8888/TCP   5d23h   app=apollo-config
apollo-portal        ClusterIP   192.168.31.38     <none>        8060/TCP   25h     app=apollo-portal
eureka               ClusterIP   None              <none>        8761/TCP   3d23h   app=eureka
gateway-service      ClusterIP   192.168.230.235   <none>        8080/TCP   9m27s   app=gateway
my-service           ClusterIP   192.168.186.163   <none>        3306/TCP   5h10m   <none>
redis-service        ClusterIP   192.168.143.180   <none>        7000/TCP   75m     <none>
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容