Search code examples
pythonpython-3.xkuberneteskubernetes-python-client

Kubernetes Python Client : update deployment spec with affinity


from kubernetes import client, config
config.load_kube_config()
api = client.AppsV1Api()

deployment = api.read_namespaced_deployment(name='foo', namespace='bar')

i tried to add affinity object to deployment spec i got this error

deployment.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms = [{'nodeSelectorTerms':[{'matchExpressions':[{'key': 'kubernetes.io/hostname','operator': 'NotIn','values': ["awesome-node"]}]}]}]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'V1DeploymentSpec' object has no attribute 'affinity'

Solution

  • You're looking at the wrong place. Affinity belongs to pod template spec (deployment.spec.template.spec.affinity) while you're looking at deployment spec (deployment.spec.affinity).

    Here's how to completely replace existing affinity (even if it's None):

    from kubernetes import client, config
    config.load_kube_config()
    api = client.AppsV1Api()
    
    # read current state
    deployment = api.read_namespaced_deployment(name='foo', namespace='bar')
    
    # check current state
    #print(deployment.spec.template.spec.affinity)
    
    # create affinity objects
    terms = client.models.V1NodeSelectorTerm(
        match_expressions=[
            {'key': 'kubernetes.io/hostname',
             'operator': 'NotIn',
             'values': ["awesome-node"]}
        ]
    )
    node_selector = client.models.V1NodeSelector(node_selector_terms=[terms])
    node_affinity = client.models.V1NodeAffinity(
        required_during_scheduling_ignored_during_execution=node_selector
    )
    affinity = client.models.V1Affinity(node_affinity=node_affinity)
    
    # replace affinity in the deployment object
    deployment.spec.template.spec.affinity = affinity
    
    # finally, push the updated deployment configuration to the API-server
    api.replace_namespaced_deployment(name=deployment.metadata.name,
                                      namespace=deployment.metadata.namespace,
                                      body=deployment)