<p>I have two applications running in K8. <code>APP A</code> has write access to a data store and <code>APP B</code> has read access.</p>

<p><code>APP A</code> needs to be able to change <code>APP B</code>'s running deployment.</p>

<p>How we currently do this is manually by kicking off a process in <code>APP A</code> which adds a new DB in the data store (say db <code>bob</code>). Then we do:</p>

<pre><code>kubectl edit deploy A
</code></pre>

<p>And change an environment variable to <code>bob</code>. This starts a rolling restart of all the pods of <code>APP B</code>. We would like to automate this process.</p>

<p>Is there anyway to get <code>APP A</code> to change the deployment config of <code>APP B</code> in k8? </p>

Filipe Teixeira
<p>Firstly answering your main question:</p>

<blockquote>
  <p>Is there anyway to get a service to change the deployment config of another service in k8?</p>
</blockquote>

<p>From my understanding you are calling it Service A and B for it's purpose in the real life, but to facilitate understanding I suggested an edit to call them <code>APP A</code> and <code>APP B</code>, because:</p>

<blockquote>
  <p>In Kubernetes, a <a href="https://kubernetes.io/docs/concepts/services-networking/service/#service-resource" rel="nofollow noreferrer">Service</a> is an <strong>abstraction which defines a logical set of Pods</strong> and a policy by which to access them (sometimes this pattern is called a micro-service).</p>
</blockquote>

<p>So if in your question you meant:</p>

<p>"Is there anyway to get <code>APP A</code> to change the deployment config of <code>APP B</code> in k8?"</p>

<p>Then <strong>Yes</strong>,  you can give a pod admin privileges to manage other components of the cluster using the <strong><code>kubectl set env</code></strong> command to change/add envs.</p>

<p>In order to achieve this, you will need:</p>

<ul>
<li><a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/#service-account-permissions" rel="nofollow noreferrer">A Service Account</a> with needed permissions in the namespace.

<ul>
<li>NOTE: In my example below since I don't know if you are working with multiple namespaces I'm using a <a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-and-clusterrole" rel="nofollow noreferrer">ClusterRole</a>, granting <code>cluster-admin</code>  to a specific user. If you use only 1 namespace for these apps, consider a Role instead.</li>
</ul></li>
<li>A <a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding" rel="nofollow noreferrer">ClusterRoleBinding</a> binding the permissions of the service account to a role of the Cluster. </li>
<li>The <a href="https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-on-linux" rel="nofollow noreferrer">Kubectl client</a> inside the pod (manually added or modifying the docker-image) on <code>APP A</code></li>
</ul>

<p><strong>Steps to Reproduce:</strong></p>

<ul>
<li>Create a deployment to apply the cluster-admin privileges, I'm naming it <code>manager-deploy.yaml</code>:</li>
</ul>

<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: manager-deploy
  labels:
    app: manager
spec:
  replicas: 1
  selector:
    matchLabels:
      app: manager
  template:
    metadata:
      labels:
        app: manager
    spec:
      serviceAccountName: k8s-role    
      containers:
        - name: manager
          image: gcr.io/google-samples/node-hello:1.0
</code></pre>

<ul>
<li>Create a deployment with a environment var, mocking your Service B. I'm naming it <code>deploy-env.yaml</code>:</li>
</ul>

<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: env-deploy
  labels:
    app: env-replace
spec:
  replicas: 1
  selector:
    matchLabels:
      app: env-replace
  template:
    metadata:
      labels:
        app: env-replace
    spec:
      serviceAccountName: k8s-role    
      containers:
        - name: env-replace
          image: gcr.io/google-samples/node-hello:1.0
          env:
          - name: DATASTORE_NAME
            value: "john"
</code></pre>

<ul>
<li>Create a <code>ServiceAccount</code> and a <code>ClusterRoleBinding</code> with <code>cluster-admin</code> privileges, I'm naming it <code>service-account-for-pod.yaml</code> (notice it's <code>mentioned in manager-deploy.yaml</code>:</li>
</ul>

<pre><code>kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: k8s-role
subjects:
- kind: ServiceAccount
  name: k8s-role
  namespace: default
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: k8s-role
</code></pre>

<ul>
<li>Apply the <code>service-account-for-pod.yaml</code>, <code>deploy-env.yaml</code>, <code>manager-deploy.yaml</code>and list current environment variables from <code>deploy-env</code> pod:</li>
</ul>

<pre><code>$ kubectl apply -f manager-deploy.yaml 
deployment.apps/manager-deploy created
$ kubectl apply -f deploy-env.yaml 
deployment.apps/env-deploy created
$ kubectl apply -f service-account-for-pod.yaml 
clusterrolebinding.rbac.authorization.k8s.io/k8s-role created
serviceaccount/k8s-role created

$ kubectl exec -it env-deploy-fbd95bb94-hcq75 -- printenv
DATASTORE_NAME=john
</code></pre>

<ul>
<li>Shell into the <code>manager pod</code>, download the <code>kubectl</code> binary and apply the <code>kubectl set env deployment/deployment_name VAR_NAME=VALUE</code>:</li>
</ul>

<pre><code>$ kubectl exec -it manager-deploy-747c9d5bc8-p684s -- /bin/bash

root@manager-deploy-747c9d5bc8-p684s:/# curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
root@manager-deploy-747c9d5bc8-p684s:/# chmod +x ./kubectl
root@manager-deploy-747c9d5bc8-p684s:/# mv ./kubectl /usr/local/bin/kubectl

root@manager-deploy-747c9d5bc8-p684s:/# kubectl set env deployment/env-deploy DATASTORE_NAME=bob     
</code></pre>

<ul>
<li>Verify the <code>env var value</code> on the pod (notice that the pod is recreated when deployment is modified: </li>
</ul>

<pre><code>$ kubectl exec -it env-deploy-7f565ffc4-t46zc -- printenv
DATASTORE_NAME=bob
</code></pre>

<p>Let me know in the comments if you have any doubt on how to apply this solution to your environment.</p>
