Search code examples
kubernetesskaffold

Tie skaffold profile to namespace


Is there a way to tie a skaffold profile to a namespace? I'd like to make sure that dev, staging and prod deployments always go to the right namespace. I know that I can add a namespace to skaffold run like skaffold run -p dev -n dev but that's a little error prone. I'd like to make my builds even safer by tying profiles to namespaces.

I've tried adding the following to my skaffold.yaml based on the fact that there's a path in skaffold.yaml which is build/cluster/namespace but I suspect I'm misunderstanding the purpose of the cluster spec.

profiles:
- name: local
  patches:
  - op: replace
    path: /build/artifacts/0/cluster/namespace
    value: testing

but I get the error

 ❮❮❮ skaffold render -p local
FATA[0000] creating runner: applying profiles: applying profile local: invalid path: /build/artifacts/0/cluster/namespace

I've tried other variants of changing the cluster namespace but all of them fail.


Solution

  • if TL/DR: please go directly to "solution" (the last section)

    Is there a way to tie a skaffold profile to a namespace? I'd like to make sure that dev, staging and prod deployments always go to the right namespace. I know that I can add a namespace to skaffold run like skaffold run -p dev -n dev but that's a little error prone. I'd like to make my builds even safer by tying profiles to namespaces.

    At the beginning we need to clarify two things, namely if we are talking about namespaces in build or deploy stage of the pipeline. On one hand you write, that you want to make sure that dev, staging and prod deployments always go to the right namespace so I'm assuming you're rather interested in setting the appropriate namespace on your kubernetes cluster in which built images will be eventually deployed. Hovewer later you mentioned also about making builds even safer by tying profiles to namespaces. Please correct me if I'm wrong but my guess is that you rather mean namespaces at the deploy stage.

    So answering your question: yes, it is possible to tie a skaffold profile to a specific namespace.

    I've tried adding the following to my skaffold.yaml based on the fact that there's a path in skaffold.yaml which is build/cluster/namespace but I suspect I'm misunderstanding the purpose of the cluster spec.

    You're right, there is such path in skaffold.yaml but then your example should look as follows:

    profiles:
    - name: local
      patches:
      - op: replace
        path: /build/cluster/namespace
        value: testing
    

    Note that cluster element is on the same indentation level as artifacts. As you can read in the reference:

    cluster:    #   beta describes how to do an on-cluster build.
    

    and as you can see, most of its options are related with kaniko. It can be also patched in the same way as other skaffold.yaml elements in specific profiles but anyway I don't think this is the element you're really concerned about so let's leave it for now.

    Btw. you can easily validate your skaffold.yaml syntax by runnig:

    skaffold fix
    

    If every element is properly used, all the indentation levels are correct etc. it will print:

    config is already latest version
    

    otherwise something like the error below:

    FATA[0000] creating runner: applying profiles: applying profile prod: invalid path: /build/cluster/namespace
    

    solution

    You can make sure your deployments go to the right namespace by setting kubectl flags. It assumes you're using docker as builder and kubectl as deployer. As there are plenty of different builders and deployers supported by skaffold the e.g. you deploy with helm the detailed solution may look quite different.

    One very important caveat: the path must be already present in your general config part, otherwise you won't be able to patch it in profiles section e.g.:

    if you have in your profiles section following patch:

    profiles:
    - name: prod
      patches:
      - op: replace
        path: /build/artifacts/0/docker/dockerfile
        value: DifferentNameForDockerfile
    

    following section must be already present in your skaffold.yaml:

    build:
      artifacts:
      - image: skaffold-example
        docker:
          dockerfile: Dockerfile # the pipeline will fail at build stage
    

    Going back to our namaspaces, first we need to set default values in deploy section:

    deploy:
      kubectl:
        manifests:
        - k8s-pod.yaml
        flags:
          global: # additional flags passed on every command.
          - --namespace=default
    #     apply: # additional flags passed on creations (kubectl apply).
    #     - --namespace=default
    #     delete: # additional flags passed on deletions (kubectl delete).
    #     - --namespace=default
    

    I set only global flags but this is also possible to set for apply and delete commands separately.

    In next step we need to override our default value (they must be already present, so we can override them) in our profiles:

    profiles:
    - name: dev
      patches:
      - op: replace
        path: /deploy/kubectl/flags/global/0
        value: --namespace=dev
    - name: staging
      patches:
      - op: replace
        path: /deploy/kubectl/flags/global/0
        value: --namespace=staging
    - name: prod
      patches:
      - op: replace
        path: /deploy/kubectl/flags/global/0
        value: --namespace=prod
    

    Then we can run:

    skaffold run --render-only --profile=prod
    

    As we can see our Pod is going to be deployed in prod namespace of our kubernetes cluster:

    Generating tags...
     - skaffold-example -> skaffold-example:v1.3.1-15-g11d005d-dirty
    Checking cache...
     - skaffold-example: Found Locally
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        app.kubernetes.io/managed-by: skaffold-v1.3.1
        skaffold.dev/builder: local
        skaffold.dev/cleanup: "true"
        skaffold.dev/deployer: kubectl
        skaffold.dev/docker-api-version: "1.39"
        skaffold.dev/profile.0: prod
        skaffold.dev/run-id: b83d48db-aec8-4570-8cb8-dbf9a7795c00
        skaffold.dev/tag-policy: git-commit
        skaffold.dev/tail: "true"
      name: getting-started
      namespace: prod
    spec:
      containers:
      - image: skaffold-example:3e4840dfd2ad13c4d32785d73641dab66be7a89b43355eb815b85bc09f45c8b2
        name: getting-started