# How to install Spinnaker in a Kubernetes Cluster?

Installing Spinnaker in a Kubernetes cluster is very straightforward. Here are the things we will do:

* Install Spinnaker Operator
    
* Install Spinnaker
    
    * Modify spinnakerservice. (Add overridebaseUrl & GitHub Oath)
        
* Exposing spinnaker via Ingress
    
    * Install nginx ingress controller
        
    * Create an ingress manifest
        
    * Route Loadbalancer IP to a domain (deck and gate)
        

* Add SSL to a domain via cert-manager
    
    * Installing cert manager
        
    * clusterissuer and certificates manifest
        
* Demo: Create a simple CICD flow using Github (CI), Docker Hub (Registry) and Spinnaker(CD)
    
    * Configure a provider
        
    * Create a Sample CD pipeline
        

**<mark>Prerequisite</mark>**

* A kubernetes cluster. In my case I'm having Digital Ocean managed Kubernetes with (4vcpu and 8gbram-&gt; for nodes). If you are looking at self-hosted k8s, check Metallb for load balancing, else not needed as long as your infrastructure supports it.
    

**<mark>Install Spinnaker Operator</mark>**

Instructions: [https://github.com/armory/spinnaker-operator](https://github.com/armory/spinnaker-operator)

**<mark>Install Spinnaker</mark>**

Instructions: [https://github.com/armory/spinnaker-kustomize-patches](https://github.com/armory/spinnaker-kustomize-patches)

* **Modify the SpinnakerService**
    

Here we modify the `spinnakerservice.yaml` by adding the overridebaseurl and oauth2 for Github. Get your GH api keys:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1677986454531/f188f6a5-fdb2-4d85-a64b-9dc169ca2286.png align="center")

We need to prepare the `kind: SpinnakerService` to accomodate custom domain and Github SSO by editing `spinnakerservice.yml`:

```yaml

      security:                # Authentication and authorization.
        uiSecurity:
          overrideBaseUrl: https://deck.spinnaker.asherl.com
        apiSecurity:
          overrideBaseUrl: https://gate.spinnaker.asherl.com 
        authn:
          oauth2:
            enabled: true
            client:
              clientId: ab0c2XXXXXXXXXX24fbb81
              clientSecret: 819c736da46XXXXXXXXX712847f1f0c
              accessTokenUri: https://github.com/login/oauth/access_token
              userAuthorizationUri: https://github.com/login/oauth/authorize
              scope: user:email
            resource:
              userInfoUri: https://api.github.com/user
            userInfoRequirements: {}
            userInfoMapping:
              email: email
              firstName: ''
              lastName: name
              username: login
            provider: GITHUB
```

Then hit:

```bash
# Build the kustomize template and deploy in kubernetes
kustomize build . | kubectl apply -f -
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1677979834657/9f194e4f-8e9c-4913-a91c-d4ce508fd57f.png align="center")

* **<mark>Exposing spinnaker via Ingress</mark>**
    
    * Install nginx ingress controller
        
        * Instructions: [https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-helm/](https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-helm/)
            
        
        ```bash
        helm repo add nginx-stable https://helm.nginx.com/stable
        helm repo update
        
        helm install my-release nginx-stable/nginx-ingress
        ```
        
    
    This will create a **Loadbalancer** service.
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1677985156779/fbe074b9-d0e2-4b75-8c88-ea07b581c639.png align="center")
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1677985214644/b9510739-16c9-43a6-822d-90f550300c02.png align="center")
    
    * Create an ingress manifest. Here you only need to change the host.
        
    
    ```yaml
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: spinnaker-ui-ingress
      namespace: spinnaker
      annotations:
        kubernetes.io/tls-acme: "true"
        kubernetes.io/ingress.class: "nginx"
        cert-manager.io/cluster-issuer: "letsencrypt-prod"
        acme.cert-manager.io/http01-edit-in-place: "true"
        nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    spec:
      tls:
      - hosts:
        - deck.spinnaker.asherl.com
        secretName: spin-deck-tls
      rules:
        - host: deck.spinnaker.asherl.com 
          http:
            paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                    name: spin-deck
                    port:
                      number: 9000
    
    ---
    
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: spinnaker-api-ingress
      namespace: spinnaker
      annotations:
        kubernetes.io/tls-acme: "true"
        kubernetes.io/ingress.class: "nginx"
        cert-manager.io/cluster-issuer: "letsencrypt-prod"
        acme.cert-manager.io/http01-edit-in-place: "true"
        nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    spec:
      tls:
      - hosts:
        - gate.spinnaker.asherl.com
        secretName: spin-gate-tls
      rules:
        - host: "gate.spinnaker.asherl.com" 
          http:
            paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                    name: spin-gate
                    port:
                      number: 8084
    ```
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1677985515456/bf0d5582-15fb-4b48-82b6-215e05c850d3.png align="center")
    
    * Route Loadbalancer IP to a domain via your DNS provider (deck and gate)
        

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1677985649601/d412a37e-000b-4a52-b728-a462d8a399a1.png align="center")

* <mark>Add SSL to a domain via cert-manager</mark>
    
    * Installing cert manager
        
    
    ```bash
    kubectl create namespace cert-manager
    helm repo add jetstack https://charts.jetstack.io
    helm repo update
    
    kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.crds.yaml
    
    helm install \
      cert-manager jetstack/cert-manager \
      --namespace cert-manager \
      --create-namespace \
      --version v1.11.0 \
      # --set installCRDs=true
    ```
    

* clusterissuer and certificates manifests
    
    * clusterissuer.yaml
        
    * ```yaml
        apiVersion: cert-manager.io/v1
        kind: ClusterIssuer
        metadata:
          name: letsencrypt-prod
          namespace: spinnaker
        spec:
          acme:
            # Email address used for ACME registration
            email: asher01000001@gmail.com
            server: https://acme-v02.api.letsencrypt.org/directory
            privateKeySecretRef:
              # Name of a secret used to store the ACME account private key
              name: letsencrypt-prod-private-key
            # Add a single challenge solver, HTTP01 using nginx
            solvers:
            - http01:
                ingress:
                  class: nginx
        ```
        
* certificate.yaml
    

* ```yaml
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: my-domain-spinnaker  
      namespace: spinnaker
    spec:
      secretName: test-domain-tls
      issuerRef:
        name: letsencrypt-prod
        kind: ClusterIssuer
      duration: 2160h # 90d
      renewBefore: 720h # 30d before SSL will expire, renew it
      dnsNames:
        - "deck.spinnaker.asherl.com"
        - "gate.spinnaker.asherl.com"
    ```
    
    Then we apply:
    
* ```bash
     k apply -f certificate.yaml -f clusterissuer.yaml
    ```
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1677986124205/d726b1b3-6f4f-4add-8935-79012fc9353f.png align="center")
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1677986158687/ca44a2d9-93a8-46d6-8b8f-7d24922cfc28.png align="center")
    
    **<mark>Demo: Create a simple CD flow</mark>**
    

We will be using Kubernetes as our provider. Create a manifest file. (e.g. Deploying simple nginx application)

You can use AWS, Azure, etc to deploy: [https://docs.armory.io/continuous-deployment/installation/armory-operator/op-manifest-reference/providers/](https://docs.armory.io/continuous-deployment/installation/armory-operator/op-manifest-reference/providers/)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1678005255353/8be27b8d-9a3b-46d4-8cb1-f0a3efbac479.png align="center")

**<mark>Congratulations!</mark>**
