环境说明

  • Kubernetes Version: v1.17.9

  • 操作系统: CentOS 7.8.2003

  • Helm Version: v3.2.1

  • Spinnaker Version: 1.26.3

    spinnaker 版本说明

spinnaker 组件说明

  • Deck:前端web页面 端口9000

  • Gate:API网关,所有程序通过gate与spinnaker通信。 端口8084

  • Orca:编排引擎,定义管道或任务,并管理阶段和任务,协调其他Spinnaker服务。 端口8083

  • Clouddriver: 云厂商适配器,负责对云厂商的变更资源调用。 端口7002

  • Front50:用于保存应用程序、管道、项目和通知的元数据。 端口8080

  • Rosco:为各种运供应商生成不可变的VM镜像。 端口 8087

  • Igor: 持续集成系统集成,触发管道。端口 8088

  • Echo:消息通知,负责发送通知。端口 8089

  • Fiat: 认证授权服务。端口 7003

  • Kayenta:自动化的金丝雀分析。端口 8090

  • Halyard: Spinnaker生命周期配置管理工具。端口 8064

组件关联图 如下所示

image-20210527113202591

使用 helm 安装部署

注意 示例演示环境使用 openwrt 进行扶墙处理;在使用 helm 部署前,首先需要确认你的梯子够不够稳,如果不稳的话建议使用的是手动部署。

helm 添加仓库

1
2
3
4
5
6
7
helm repo add stable https://charts.helm.sh/stable

helm repo update

helm search repo spinnaker
NAME                    CHART VERSION   APP VERSION     DESCRIPTION                                       
stable/spinnaker        2.2.6           1.16.2          DEPRECATED - Open source, multi-cloud continuou...

创建 values.yaml 部署文件

示例部署使用了 Nfs storageClass 作为 pvc & pv 的管理。生产环境不太建议。

原 helm values.yaml 部署文件可以使用此 链接 查看,或 使用下面命令进行打印输出。

1
 helm show values stable/spinnaker

修改完成后的 prod-values.yaml 文件查看

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
cat > prod-values.yaml << EOF
halyard:
  spinnakerVersion: 1.26.3
  image:
    repository: gcr.io/spinnaker-marketplace/halyard
    tag: 1.32.0
  persistence:
    enabled: true
    storageClass: nfs-retain

minio:
  enabled: true
  image:
    tag: RELEASE.2020-01-03T19-12-21Z
  service:
    type: ClusterIP
  accessKey: admin
  secretKey: spinnaker
  persistence:
    enabled: true
    storageClass: "nfs-retain"

redis:
  enabled: true
  password: spinnaker
  master:
    persistence:
      storageClass: nfs-retain
  cluster:
    enabled: false
EOF
1
2
3
kubectl create ns spinnaker

helm upgrade --install spinnaker -f ./prod-values.yaml -n spinnaker stable/spinnaker

image-20210524180800720

image-20210524180818188

使用 traefik 暴露前端页面

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
cat <<EOF | kubectl apply -f -
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: spin-deck
  namespace: spinnaker
spec:
  entryPoints:
    - web
  routes:
  - match: Host(\`spinnaker.treesir.pub\`) && PathPrefix(\`/\`)
    kind: Rule
    services:
    - name: spin-deck 
      port: 9000 
EOF



cat <<EOF | kubectl apply -f -
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: spin-gate
  namespace: spinnaker
spec:
  entryPoints:
    - web
  routes:
  - match: Host(\`spin-gate.treesir.pub\`) && PathPrefix(\`/\`)
    kind: Rule
    services:
    - name: spin-gate
      port: 8084
EOF

添加 host 记录

1
2
sudo vi /etc/hosts
192.168.8.30 spinnaker.treesir.pub # 解析至对应 ip

image-20210527114020178

1
2
3
4
5
6
7
8
9
## 设置deck与gate的域名

kubectl exec -it spinnaker-spinnaker-halyard-0 bash -n spinnaker 


hal config security ui edit --override-base-url http://spinnaker.treesir.pub
hal config security api edit --override-base-url http://spin-gate.treesir.pub

hal deploy apply # 应用应用生效

配置管理 openLdap

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
kubectl exec -it spinnaker-spinnaker-halyard-0 bash -n spinnaker 



hal config security authn ldap edit \
  --user-search-base 'ou=users,dc=treesir,dc=pub' \
  --url 'ldap://192.168.8.1:389' \
  --user-search-filter 'cn={0}' \
  --manager-dn 'cn=admin,dc=treesir,dc=pub' \
  --manager-password '123456'

 
hal config security authn ldap enable



hal deploy apply # 执行生效

image-20210527142033759

image-20210527142050080

备份

  • 创建备份

    1
    
    hal backup create
    

    image-20210527142308354

  • 恢复备份

    1
    
    hal backup restore --backup-path /home/spinnaker/halyard-xxxx.tar
    

删除部署

1
hal deploy clean

请注意,此命令将破坏目标部署环境中的所有 Spinnaker 组件。因此,请谨慎使用它并备份您的配置,以防您要还原它。

删除 Spinnaker 后,通过运行下面命令删除 halyard,下面命令在 helm 部署的集群中 不适应 ,在 helm 中 可以直接执行 helm delete xx 进行删除

1
sudo ~/.hal/uninstall.sh  

授权管理

Fiat 组件是 Spinnaker 的授权(authz)微服务。它可以授予用户执行管道,查看基础结构等访问权限。默认情况下处于禁用状态。与身份验证非常相似,Spinnaker 允许使用各种可插入的授权机制。使用 Fiat 主要可以实现如下功能:

  • 限制对特定的clouddriver account 访问。(读、写)

  • 限制对特定的APP 应用程序访问。(读、写、执行)

  • 使用触发器对访问控制的程序运行管道。

  • 支持角色提供者中定期更新用户角色。

  • 当资源没有 定义允许谁访问资源时,就被认为是不受限制的。

  • 如果集群账户不受限制,则任何用户都可以使用该帐户部署新应用程序。

  • 如果应用程序不受限制,则任何用户都可以将该应用程序部署到其他帐户中。还能看到服务器组内的基本信息,例如实例名称。

  • Spinnaker中的每个权限可以赋予角色,而不能是哪一个用户。

  • 一个帐户下可以包含多个应用程序,而应用程序也可以跨越多个帐户。

  • 授予对帐户的访问权不会同时授予对应用程序的访问权,反之亦然。

Spinnaker支持: YamlFile、GitHubTeams、GoogleGroups、LDAPGroups、SAMLGroups。

  • YamlFile: 使用yaml文件描述用户与角色的绑定。

  • LDAPGroups:将用户与其在LDAP中所属组绑定

授权(根据LDAP组进行同步)

image-20210527143430060

image-20210527150049089

使用 关联 openLdap 命令方式

与下面 yaml 方式部署 二选一

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
hal config security authz ldap edit \
	--url 'ldap://192.168.8.1:389/dc=treesir,dc=pub' \
	--manager-dn 'cn=admin,dc=treesir,dc=pub' \
	--manager-password '123456' \
	--user-dn-pattern 'cn={0}' \
	--group-search-base 'ou=groups' \
	--group-search-filter 'uniqueMember={0}' \
	--group-role-attributes 'cn' \
	--user-search-filter 'cn={0}'
         
hal config security authz edit --type ldap
hal config security authz enable

cat ~/.hal/config  # 检查对应配置文件
...
    authz:
      groupMembership:
        service: LDAP
        google:
          roleProviderType: GOOGLE
        github:
          roleProviderType: GITHUB
        file:
          roleProviderType: FILE
        ldap:
          roleProviderType: LDAP
          url: ldap://192.168.8.1:389/dc=treesir,dc=pub
          managerDn: cn=admin,dc=treesir,dc=pub
          managerPassword: '123456'
          userDnPattern: cn={0}
          groupSearchBase: ou=groups
          userSearchFilter: cn={0}
          groupSearchFilter: uniqueMember={0}
          groupRoleAttributes: cn
      enabled: true
...
     
hal deploy apply # 执行生效

生效后,可以选择使用下面的 traefik 对 认证授权组件暴露出来,或者是使用内部ip进行访问

测试是否有生效

1
2
3
curl -X POST http://spin-fiat.treesir.pub/roles/sync

curl http://spin-fiat.treesir.pub/authorize/userid 2>&1|grep -A 10 roles

userid 对应用户需要在 前端页面进行登录,不然会提示接口 404

image-20210527154236830

使用 yaml 方式

1
2
3
4
#使用Yaml文件
hal config security authz enable 
hal config security authz file edit --file-path=$HOME/userrole.yaml 
hal config security authz edit --type file

认证授权服务组件 fiat 使用 traefik 进行暴露

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
cat <<EOF | kubectl apply -f -
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: spin-fiat
  namespace: spinnaker
spec:
  entryPoints:
    - web
  routes:
  - match: Host(\`spin-fiat.treesir.pub\`) && PathPrefix(\`/\`)
    kind: Rule
    services:
    - name: spin-fiat
      port: 7003
EOF

授权管理

现在我们有两个组,设置 ops 组只读,devops 组可以读写

image-20210527154823275

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
kubectl exec -it spinnaker-spinnaker-halyard-0 bash -n spinnaker

hal config provider kubernetes account edit default \
--add-read-permission devops,ops \
--add-write-permission devops

# 下面这两个可以指定删除权限
--remove-read-permission
--remove-write-permission


cat ~/.hal/config  # 检查配置文件
...
    kubernetes:
      enabled: true
      accounts:
      - name: default
        requiredGroupMembership: []
        providerVersion: V2
        permissions:
          READ:
          - devops
          WRITE:
          - devops
...

hal deploy apply # 执行生效

使用 yaml 定义角色和用户

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1.首先先关闭LDAP权限。 
hal config security authz disable 


vi $HOME/userrole.yml 
users:
 - username: yangzun
   roles:
   - devops
   - bar
   - foo
 - username: test
   roles:
   - test
   - bar
 - username: anonymous
   roles: []

2.配置Yaml文件
hal config security authz enable 
hal config security authz file edit --file-path=$HOME/userrole.yml
hal config security authz edit --type file


cat ~/.hal/config
...
    authz:            
      groupMembership:
        service: FILE
        google:   
          roleProviderType: GOOGLE
        github:    
          roleProviderType: GITHUB
        file:  
          roleProviderType: FILE
          path: /home/spinnaker/userrole.yml
      enabled: true 
...

hal deploy apply # 执行生效

创建管理员权限

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
vi ~/.hal/default/profiles/fiat-local.yml
fiat:
  admin:
    roles:
      - devops-admin # 将此组 添加管理员权限
      
vi $HOME/userrole.yml  # 用户添加进组
users:
 - username: yangzun
   roles:
   - devops
   - bar
   - foo
   - devops-admin  # 设置使用刚添加的权限
...
      
      
hal deploy apply

关联 jenkins

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
kubectl exec -it spinnaker-spinnaker-halyard-0 bash -n spinnaker

hal config ci jenkins enable

hal config ci jenkins master add jenkins-master \
    --address http://ci.treesir.pub \
    --username yangzun \
    --password 117a723c9b729b2256e3ffc40c3d2b2156

## 启用csrf
hal config ci jenkins master edit jenkins-master --csrf true

cat ~/.hal/config 
...
  ci:
    jenkins:
      enabled: true
      masters:
      - name: jenkins-master
        permissions: {}
        address: http://ci.treesir.pub
        username: yangzun
        password: 117a723c9b729b2256e3ffc40c3d2b2156
        csrf: true
...

hal deploy apply  # 应用并生效

在 Jenkins 中安装Strict Crumb Issuer插件

image-20210528101554481

全局安全设置中 开启对应参数

image-20210528105304316

测试;在 spinnaker 中 新建 jenkins 类型触发 ,查看是否可以看到对应 jenkins 中的 pipeline

image-20210528105846756

消息通知之邮件通知

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 kubectl exec -it spinnaker-spinnaker-halyard-0 bash -n spinnaker
 
cd /home/spinnaker/.hal/default/profiles

cat >> settings-local.js << EOF
window.spinnakerSettings.notifications.email.enabled = true;
EOF

cat > echo-local.yml << EOF
mail:
  enabled: true
  from: amoaloas@163.com
spring:
  mail:
    host: smtp.163.com
    username: amoaloas@163.com
    password: FZXIQXXO
    protocol: smtp
    default-encoding: utf-8
    properties:
      mail:
        display:
          sendname: SpinnakerAdmin
        smtp:
          port: 465
          auth: true
          starttls:
            enable: true
            required: true
          ssl:
            enable: true
        transport:
          protocol: smtp
        debug: true
EOF


hal deploy apply # 应用生效

更改时区

1
2
3
hal config edit --timezone 'Asia/Shanghai'

hal deploy apply # 应用生效

开启制品空间

  • 开启http

    1
    2
    3
    4
    5
    6
    
    hal config artifact http enable
    
    echo ${USERNAME}:${PASSWORD} > $USERNAME_PASSWORD_FILE
    
    hal config artifact http account add my-http-account \
        --username-password-file $USERNAME_PASSWORD_FILE  # 添加对应账号密码
    

开启特征功能

1
2
3
4
hal config features edit --pipeline-templates true
hal config features edit --artifacts true

hal config features edit --managed-pipeline-templates-v2-ui true

开启对 pipeline 的权限管理

1
2
3
4
5
6
7
8
9
~/.hal/default/profiles/orca-local.yml
tasks:
  useManagedServiceAccounts: true

~/.hal/default/profiles/settings-local.js
window.spinnakerSettings.feature.managedServiceAccounts = true;


hal deploy apply # 应用生效

添加 k8s 集群

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
hal config provider kubernetes enable

hal config provider kubernetes account add k3s \
  --context $(kubectl config current-context --kubeconfig ~/.kube/k3s) \
  --service-account true \
  --omit-namespaces=kube-system,kube-public \
  --kubeconfig-file ~/.kube/k3s \
  --provider-version v2
  
hal config deploy edit --type distributed --account-name  k3s
  • 1
    2
    3
    4
    
    CONTEXT=$(kubectl config current-context)
    
    hal config provider kubernetes account add default \
        --context $CONTEXT
    

添加 dokcer 镜像仓库

1
2
3
4
5
hal config provider docker-registry enable --no-validate
hal config provider docker-registry account add my-harborregistry \
--address https://harbor.treesir.pub \
--username yangzun \
--password 123456

helm 部署 spinnaker 添加 集群

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

kubectl get po --kubeconfig ~/.kube/k3s --all-namespaces # 测试 对应 config 文件是否有效


kubectl create secret generic --from-file=$HOME/.kube/config kube-config -n spinnaker 

kubeConfig:
  enabled: true
  secretName: kube-config
  secretKey: config
  contexts:
==
  - my-context
  # This is the context from the list above that you would like
  # to deploy Spinnaker itself to.
  deploymentContext: my-context

手动启动 halyard

  • 部署 minio

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    
    kubectl create ns devops-minio
    
    helm repo add minio https://helm.min.io/
    
    helm repo update 
    
    cat > prod-values.yaml << EOF
    image:
      tag: RELEASE.2021-03-17T02-33-02Z
    accessKey: "admin"
    secretKey: "ancun123"
    persistence:
      existingClaim: "devops-minio-pvc"
      accessMode: ReadWriteOnce
      size: 100Gi
    service:
      type: NodePort
    buckets:
      - name: spinnaker
        policy: none
        purge: false
    EOF
    
    cat > devops-minio-pvPvc.yaml << EOF
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: devops-minio-pv
    spec:
      storageClassName: local-storage  # Local PV
      capacity:
        storage: 100Gi
      volumeMode: Filesystem
      accessModes:
      - ReadWriteOnce
      local:
        path: /data/devops/minio
      nodeAffinity:
        required:
          nodeSelectorTerms:
          - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
              - mn105
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: devops-minio-pvc
      namespace: devops-minio
    spec:
      storageClassName: local-storage 
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 100Gi
    EOF
    
    mkdir -p /data/devops/minio # 创建 localPv 目录
    kubectl apply -f ./devops-minio-pvPvc.yaml
    
    
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
docker pull gcr.io/spinnaker-marketplace/halyard:1.32.0

mkdir ~/.hal
chmod -R 777 ~/.hal

docker run -itd --name halyard \
-v /root/.hal:/home/spinnaker/.hal \
-v /root/.kube:/home/spinnaker/.kube \
--restart=always \
--net=host \
idocker.io/spinnaker-marketplace/halyard:1.32.0

docker exec -it halyard bash
hal config version edit --version 1.25.5
hal config edit --timezone Asia/Shanghai


hal config storage s3 edit \
--endpoint http://s3.treesir.pub \
--access-key-id admin \
--secret-access-key 12345678 \
--bucket spinnaker \
--path-style-access true

hal config storage edit --type s3



hal config security ui edit --override-base-url http://spinnaker.treesir.pub
hal config security api edit --override-base-url http://spin-gate.treesir.pub


hal config provider docker-registry enable


hal config provider kubernetes enable
hal config provider kubernetes account add default \
--context $(kubectl config current-context) \
--service-account true \
--omit-namespaces=kube-system,kube-public,cattle-system,cattle-prometheus \
--provider-version v2 \
--no-validate


hal config deploy edit \
--account-name default \
--type distributed \
--location spinnaker  # 部署集群


hal deploy apply  # 执行生效

todo