How to use image stream in deploy configuration for OpenShift

11/14/2016

I want my deploy configuration to use an image that was the output of a build configuration.

I am currently using something like this:

- apiVersion: v1
  kind: DeploymentConfig
  metadata:
    annotations:
      openshift.io/generated-by: OpenShiftNewApp
    creationTimestamp: null
    labels:
      app: myapp
    name: myapp
  spec:
    replicas: 1
    selector:
      app: myapp
      deploymentconfig: myapp
    strategy:
      resources: {}
    template:
      metadata:
        annotations:
          openshift.io/container.myapp.image.entrypoint: '["python3"]'
          openshift.io/generated-by: OpenShiftNewApp
        creationTimestamp: null
        labels:
          app: myapp
          deploymentconfig: myapp
      spec:
        containers:
        - name: myapp
          image: 123.123.123.123/myproject/myapp-staging:latest
          resources: {}
          command:
            - scripts/start_server.sh
          ports:
            - containerPort: 8000
    test: false
    triggers: []
  status: {}

I had to hard-code the integrated docker registry's IP address; otherwise Kubernetes/OpenShift is not able to find the image to pull down. I would like to not hard-code the integrated docker registry's IP address, and instead use something like this:

- apiVersion: v1
  kind: DeploymentConfig
  metadata:
    annotations:
      openshift.io/generated-by: OpenShiftNewApp
    creationTimestamp: null
    labels:
      app: myapp
    name: myapp
  spec:
    replicas: 1
    selector:
      app: myapp
      deploymentconfig: myapp
    strategy:
      resources: {}
    template:
      metadata:
        annotations:
          openshift.io/container.myapp.image.entrypoint: '["python3"]'
          openshift.io/generated-by: OpenShiftNewApp
        creationTimestamp: null
        labels:
          app: myapp
          deploymentconfig: myapp
      spec:
        containers:
        - name: myapp
          from:
            kind: "ImageStreamTag"
            name: "myapp-staging:latest"
          resources: {}
          command:
            - scripts/start_server.sh
          ports:
            - containerPort: 8000
    test: false
    triggers: []
  status: {}

But this causes Kubernetes/OpenShift to complain with:

The DeploymentConfig "myapp" is invalid.
spec.template.spec.containers[0].image: required value

How can I specify the output of a build configuration as the image to use in a deploy configuration?

Thank you for your time!

Also, oddly enough, if I link the deploy configuration to the build configuration with a trigger, Kubernetes/OpenShift knows to look in the integrated docker for the image:

- apiVersion: v1
  kind: DeploymentConfig
  metadata:
    annotations:
      openshift.io/generated-by: OpenShiftNewApp
    creationTimestamp: null
    labels:
      app: myapp-staging
    name: myapp-staging
  spec:
    replicas: 1
    selector:
      app: myapp-staging
      deploymentconfig: myapp-staging
    strategy:
      resources: {}
    template:
      metadata:
        annotations:
          openshift.io/container.myapp.image.entrypoint: '["python3"]'
          openshift.io/generated-by: OpenShiftNewApp
        creationTimestamp: null
        labels:
          app: myapp-staging
          deploymentconfig: myapp-staging
      spec:
        containers:
        - name: myapp-staging
          image: myapp-staging:latest
          resources: {}
          command:
            - scripts/start_server.sh
          ports:
            - containerPort: 8000
    test: false
    triggers:
    - type: "ImageChange"
      imageChangeParams:
        automatic: true
        containerNames:
        - myapp-staging
        from:
          kind: ImageStreamTag
          name: myapp-staging:latest
  status: {}

But I don't want the automated triggering...

Update 1 (11/21/2016): Configuring the trigger but having the trigger disabled (hence manually triggering the deploy), still left the deployment unable to find the image:

$ oc describe pod myapp-1-oodr5
Name:                   myapp-1-oodr5
Namespace:              myproject
Security Policy:        restricted
Node:                   node.url/123.123.123.123
Start Time:             Mon, 21 Nov 2016 09:20:26 -1000
Labels:                 app=myapp
                        deployment=myapp-1
                        deploymentconfig=myapp
Status:                 Pending
IP:                     123.123.123.123
Controllers:            ReplicationController/myapp-1
Containers:
  myapp:
    Container ID:
    Image:              myapp-staging:latest
    Image ID:
    Port:               8000/TCP
    Command:
      scripts/start_server.sh
    State:              Waiting
      Reason:           ImagePullBackOff
    Ready:              False
    Restart Count:      0
    Volume Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-goe98 (ro)
    Environment Variables:
      ALLOWED_HOSTS:    myapp-myproject.url
Conditions:
  Type          Status
  Ready         False 
Volumes:
  default-token-goe98:
    Type:       Secret (a volume populated by a Secret)
    SecretName: default-token-goe98
QoS Tier:       BestEffort
Events:
  FirstSeen     LastSeen        Count   From                                    SubobjectPath                           Type            Reason          Message
  ---------     --------        -----   ----                                    -------------                           --------        ------          -------
  42s           42s             1       {scheduler }                                                                                    Scheduled       Successfully assigned myapp-1-oodr5 to node.url
  40s           40s             1       {kubelet node.url}  implicitly required container POD                       Pulled          Container image "openshift3/ose-pod:v3.1.1.7" already present on machine
  40s           40s             1       {kubelet node.url}  implicitly required container POD                       Created         Created with docker id d3318e880e4a
  40s           40s             1       {kubelet node.url}  implicitly required container POD                       Started         Started with docker id d3318e880e4a
  40s           24s             2       {kubelet node.url}  spec.containers{myapp}                            Pulling         pulling image "myapp-staging:latest"
  38s           23s             2       {kubelet node.url}  spec.containers{myapp}                            Failed          Failed to pull image "myapp-staging:latest": Error: image library/myapp-staging:latest not found
  35s           15s             2       {kubelet node.url}  spec.containers{myapp}                            Back-off        Back-off pulling image "myapp-staging:latest"

Update 2 (08/23/2017): In case, this helps others, here's a summary of the solution.

triggers:    
- type: "ImageChange"
  imageChangeParams:
    automatic: true # this is required to link the build and deployment
    containerNames:
    - myapp-staging
    from:
      kind: ImageStreamTag
      name: myapp-staging:latest

With the trigger and automatic set to true, the deployment should use the build's image in the internal registry.

The other comments relating to making the build not trigger a deploy relates to a separate requirement of wanting to manually deploy images from the internal registry. Here's more information about that portion:

The build needs to trigger the deployment at least once before automatic is set to false. So far a while, I was:

  1. setting automatic to true
  2. initiate a build and deploy
  3. after deployment finishes, manually change automatic to false
  4. manually, trigger a deployment later (though I did not verify if this deployed the older, out-of-date image or not)

I was initially trying to use this manual deployment as a way for a non-developer to go into the web console and make deployments. But this requirement has since been removed, so having build trigger deployments each time works just fine for us now. Builds can build at different branches and then tag the images differently. Deployments can then just use the appropriately tagged images.

Hope that helps!

-- Zhao Li
kubernetes
openshift

1 Answer

11/14/2016

Are you constructing the resource definitions by hand?

It would be easier to use oc new-build and then oc new-app if you really need to set this up as two steps for some reason. If you just want to setup the build and deployment in one go, just use oc new-app.

For example, to setup build and deployment in one go use:

oc new-app --name myapp <repository-url>

To do it in two steps use:

oc new-build --name myapp <repository-url>
oc new-app myapp

If you still rather use hand created resources, at least use the single step variant with the --dry-run -o yaml options to see what it would create for the image stream, plus build and deployment configuration. That way you can learn from it how to do it. The bit you currently have missing is an image stream.

BTW. It looks a bit suspicious that you have the entry point set to python3. That is highly unusual. What are you trying to do as right now it looks like you may be trying to do something in a way which may not work with how OpenShift works. OpenShift is mainly about long running processes and not for doing single docker run. You can do the latter, but not how you are currently doing it.

-- Graham Dumpleton
Source: StackOverflow