Adding OpenShift doc
This commit is contained in:
parent
83b3fa8cd0
commit
0a57ebb96e
|
|
@ -0,0 +1,8 @@
|
||||||
|
KUBERNETES_PROVIDER=crc
|
||||||
|
DOCKER_ORGANIZATION=image-registry.openshift-image-registry.svc:5000/jenkins-operator
|
||||||
|
DOCKER_REGISTRY=kubernetes-operator
|
||||||
|
IMAGE_PULL_MODE=remote
|
||||||
|
JENKINS_API_PORT=0
|
||||||
|
JENKINS_API_USE_NODEPORT=false
|
||||||
|
NAMESPACE=$(oc project -q)
|
||||||
|
|
||||||
|
|
@ -7,64 +7,67 @@ metadata:
|
||||||
spec:
|
spec:
|
||||||
master:
|
master:
|
||||||
containers:
|
containers:
|
||||||
- name: jenkins-master
|
- name: jenkins-master
|
||||||
command:
|
command:
|
||||||
- /usr/bin/go-init
|
- /usr/bin/go-init
|
||||||
- '-main'
|
- '-main'
|
||||||
- /usr/libexec/s2i/run
|
- /usr/libexec/s2i/run
|
||||||
env:
|
env:
|
||||||
- name: OPENSHIFT_ENABLE_OAUTH
|
- name: OPENSHIFT_ENABLE_OAUTH
|
||||||
value: 'true'
|
value: 'true'
|
||||||
- name: OPENSHIFT_ENABLE_REDIRECT_PROMPT
|
- name: OPENSHIFT_ENABLE_REDIRECT_PROMPT
|
||||||
value: 'true'
|
value: 'true'
|
||||||
- name: DISABLE_ADMINISTRATIVE_MONITORS
|
- name: DISABLE_ADMINISTRATIVE_MONITORS
|
||||||
value: 'false'
|
value: 'false'
|
||||||
- name: KUBERNETES_MASTER
|
- name: KUBERNETES_MASTER
|
||||||
value: 'https://kubernetes.default:443'
|
value: 'https://kubernetes.default:443'
|
||||||
- name: KUBERNETES_TRUST_CERTIFICATES
|
- name: KUBERNETES_TRUST_CERTIFICATES
|
||||||
value: 'true'
|
value: 'true'
|
||||||
- name: JENKINS_SERVICE_NAME
|
- name: JENKINS_SERVICE_NAME
|
||||||
value: jenkins-operator-http-example
|
value: jenkins-operator-http-jenkins
|
||||||
- name: JNLP_SERVICE_NAME
|
- name: JNLP_SERVICE_NAME
|
||||||
value: jenkins-operator-slave-example
|
value: jenkins-operator-slave-jenkins
|
||||||
- name: JENKINS_UC_INSECURE
|
- name: JENKINS_UC_INSECURE
|
||||||
value: 'false'
|
value: 'false'
|
||||||
- name: JENKINS_HOME
|
- name: JENKINS_HOME
|
||||||
value: /var/lib/jenkins
|
value: /var/lib/jenkins
|
||||||
- name: JAVA_OPTS
|
- name: JAVA_OPTS
|
||||||
value: >-
|
value: >-
|
||||||
-XX:+UnlockExperimentalVMOptions -XX:+UnlockExperimentalVMOptions
|
-XX:+UnlockExperimentalVMOptions -XX:+UnlockExperimentalVMOptions
|
||||||
-XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1
|
-XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1
|
||||||
-Djenkins.install.runSetupWizard=false -Djava.awt.headless=true
|
-Djenkins.install.runSetupWizard=false -Djava.awt.headless=true
|
||||||
image: 'quay.io/openshift/origin-jenkins:latest'
|
image: 'quay.io/openshift/origin-jenkins:latest'
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /login
|
path: /login
|
||||||
port: 8080
|
port: 8080
|
||||||
scheme: HTTP
|
scheme: HTTP
|
||||||
initialDelaySeconds: 420
|
initialDelaySeconds: 420
|
||||||
periodSeconds: 360
|
periodSeconds: 360
|
||||||
timeoutSeconds: 240
|
timeoutSeconds: 240
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /login
|
path: /login
|
||||||
port: 8080
|
port: 8080
|
||||||
scheme: HTTP
|
scheme: HTTP
|
||||||
initialDelaySeconds: 3
|
initialDelaySeconds: 3
|
||||||
periodSeconds: 0
|
periodSeconds: 0
|
||||||
timeoutSeconds: 240
|
timeoutSeconds: 240
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpu: 600m
|
cpu: 600m
|
||||||
memory: 4Gi
|
memory: 4Gi
|
||||||
requests:
|
requests:
|
||||||
cpu: 500m
|
cpu: 500m
|
||||||
memory: 3Gi
|
memory: 3Gi
|
||||||
service:
|
service:
|
||||||
port: 8080
|
port: 8080
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
slaveService:
|
slaveService:
|
||||||
port: 50000
|
port: 50000
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
|
serviceAccount:
|
||||||
|
annotations:
|
||||||
|
serviceaccounts.openshift.io/oauth-redirectreference.jenkins: '{"kind":"OAuthRedirectReference","apiVersion":"v1","reference":{"kind":"Route","name":"jenkins-operator"}}'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -767,7 +767,12 @@ func TestEnsureExtraRBAC(t *testing.T) {
|
||||||
Roles: []rbacv1.RoleRef{},
|
Roles: []rbacv1.RoleRef{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
reconciler := New(configuration.Configuration{Client: fakeClient, Jenkins: jenkins, Scheme: scheme.Scheme}, nil, client.JenkinsAPIConnectionSettings{})
|
config := configuration.Configuration{
|
||||||
|
Client: fakeClient,
|
||||||
|
Jenkins: jenkins,
|
||||||
|
Scheme: scheme.Scheme,
|
||||||
|
}
|
||||||
|
reconciler := New(config, log.Log, client.JenkinsAPIConnectionSettings{})
|
||||||
metaObject := resources.NewResourceObjectMeta(jenkins)
|
metaObject := resources.NewResourceObjectMeta(jenkins)
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
|
@ -803,7 +808,12 @@ func TestEnsureExtraRBAC(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
reconciler := New(configuration.Configuration{Client: fakeClient, Jenkins: jenkins, Scheme: scheme.Scheme}, nil, client.JenkinsAPIConnectionSettings{})
|
config := configuration.Configuration{
|
||||||
|
Client: fakeClient,
|
||||||
|
Jenkins: jenkins,
|
||||||
|
Scheme: scheme.Scheme,
|
||||||
|
}
|
||||||
|
reconciler := New(config, log.Log, client.JenkinsAPIConnectionSettings{})
|
||||||
metaObject := resources.NewResourceObjectMeta(jenkins)
|
metaObject := resources.NewResourceObjectMeta(jenkins)
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
|
@ -845,7 +855,12 @@ func TestEnsureExtraRBAC(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
reconciler := New(configuration.Configuration{Client: fakeClient, Jenkins: jenkins, Scheme: scheme.Scheme}, nil, client.JenkinsAPIConnectionSettings{})
|
config := configuration.Configuration{
|
||||||
|
Client: fakeClient,
|
||||||
|
Jenkins: jenkins,
|
||||||
|
Scheme: scheme.Scheme,
|
||||||
|
}
|
||||||
|
reconciler := New(config, log.Log, client.JenkinsAPIConnectionSettings{})
|
||||||
metaObject := resources.NewResourceObjectMeta(jenkins)
|
metaObject := resources.NewResourceObjectMeta(jenkins)
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
|
@ -888,7 +903,12 @@ func TestEnsureExtraRBAC(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
reconciler := New(configuration.Configuration{Client: fakeClient, Jenkins: jenkins, Scheme: scheme.Scheme}, log.Log, client.JenkinsAPIConnectionSettings{})
|
config := configuration.Configuration{
|
||||||
|
Client: fakeClient,
|
||||||
|
Jenkins: jenkins,
|
||||||
|
Scheme: scheme.Scheme,
|
||||||
|
}
|
||||||
|
reconciler := New(config, log.Log, client.JenkinsAPIConnectionSettings{})
|
||||||
metaObject := resources.NewResourceObjectMeta(jenkins)
|
metaObject := resources.NewResourceObjectMeta(jenkins)
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
createVerb = "create"
|
createVerb = "create"
|
||||||
deleteVerb = "delete"
|
deleteVerb = "delete"
|
||||||
getVerb = "get"
|
getVerb = "get"
|
||||||
listVerb = "list"
|
listVerb = "list"
|
||||||
watchVerb = "watch"
|
watchVerb = "watch"
|
||||||
patchVerb = "patch"
|
patchVerb = "patch"
|
||||||
updateVerb = "update"
|
updateVerb = "update"
|
||||||
EmptyApiGroups = ""
|
//EmptyAPIGroup short hand for the empty API group while defining policies
|
||||||
OpenshiftApiGroup = "image.openshift.io"
|
EmptyAPIGroup = ""
|
||||||
BuildApiGroup = "build.openshift.io"
|
//OpenshiftAPIGroup the openshift api group name
|
||||||
|
OpenshiftAPIGroup = "image.openshift.io"
|
||||||
|
//BuildAPIGroup the openshift api group name for builds
|
||||||
|
BuildAPIGroup = "build.openshift.io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewRole returns rbac role for jenkins master
|
// NewRole returns rbac role for jenkins master
|
||||||
|
|
@ -54,22 +56,23 @@ func NewRoleBinding(name, namespace, serviceAccountName string, roleRef v1.RoleR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewDefaultPolicyRules sets the default policy rules
|
||||||
func NewDefaultPolicyRules() []v1.PolicyRule {
|
func NewDefaultPolicyRules() []v1.PolicyRule {
|
||||||
var rules []v1.PolicyRule
|
var rules []v1.PolicyRule
|
||||||
ReadOnly := []string{getVerb, listVerb, watchVerb}
|
ReadOnly := []string{getVerb, listVerb, watchVerb}
|
||||||
Default := []string{createVerb, deleteVerb, getVerb, listVerb, patchVerb, updateVerb, watchVerb}
|
Default := []string{createVerb, deleteVerb, getVerb, listVerb, patchVerb, updateVerb, watchVerb}
|
||||||
Create := []string{createVerb}
|
Create := []string{createVerb}
|
||||||
|
|
||||||
rules = append(rules, NewPolicyRule(EmptyApiGroups, "pods/portforward", Create))
|
rules = append(rules, NewPolicyRule(EmptyAPIGroup, "pods/portforward", Create))
|
||||||
rules = append(rules, NewPolicyRule(EmptyApiGroups, "pods", Default))
|
rules = append(rules, NewPolicyRule(EmptyAPIGroup, "pods", Default))
|
||||||
rules = append(rules, NewPolicyRule(EmptyApiGroups, "pods/exec", Default))
|
rules = append(rules, NewPolicyRule(EmptyAPIGroup, "pods/exec", Default))
|
||||||
rules = append(rules, NewPolicyRule(EmptyApiGroups, "configmaps", ReadOnly))
|
rules = append(rules, NewPolicyRule(EmptyAPIGroup, "configmaps", ReadOnly))
|
||||||
rules = append(rules, NewPolicyRule(EmptyApiGroups, "pods/log", ReadOnly))
|
rules = append(rules, NewPolicyRule(EmptyAPIGroup, "pods/log", ReadOnly))
|
||||||
rules = append(rules, NewPolicyRule(EmptyApiGroups, "secrets", ReadOnly))
|
rules = append(rules, NewPolicyRule(EmptyAPIGroup, "secrets", ReadOnly))
|
||||||
|
|
||||||
rules = append(rules, NewOpenShiftPolicyRule(OpenshiftApiGroup, "imagestreams", ReadOnly))
|
rules = append(rules, NewOpenShiftPolicyRule(OpenshiftAPIGroup, "imagestreams", ReadOnly))
|
||||||
rules = append(rules, NewOpenShiftPolicyRule(BuildApiGroup, "buildconfigs", ReadOnly))
|
rules = append(rules, NewOpenShiftPolicyRule(BuildAPIGroup, "buildconfigs", ReadOnly))
|
||||||
rules = append(rules, NewOpenShiftPolicyRule(BuildApiGroup, "builds", ReadOnly))
|
rules = append(rules, NewOpenShiftPolicyRule(BuildAPIGroup, "builds", ReadOnly))
|
||||||
|
|
||||||
return rules
|
return rules
|
||||||
}
|
}
|
||||||
|
|
@ -84,8 +87,7 @@ func NewPolicyRule(apiGroup string, resource string, verbs []string) v1.PolicyRu
|
||||||
return rule
|
return rule
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPolicyRule returns a policyRule allowing verbs on resources
|
// NewOpenShiftPolicyRule returns a policyRule allowing verbs on resources
|
||||||
func NewOpenShiftPolicyRule(apiGroup string, resource string, verbs []string) v1.PolicyRule {
|
func NewOpenShiftPolicyRule(apiGroup string, resource string, verbs []string) v1.PolicyRule {
|
||||||
return NewPolicyRule(apiGroup,resource,verbs)
|
return NewPolicyRule(apiGroup, resource, verbs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@ package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base/resources"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
||||||
|
|
||||||
stackerr "github.com/pkg/errors"
|
stackerr "github.com/pkg/errors"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
|
@ -15,8 +17,11 @@ import (
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) createServiceAccount(meta metav1.ObjectMeta) error {
|
func (r *ReconcileJenkinsBaseConfiguration) createServiceAccount(meta metav1.ObjectMeta) error {
|
||||||
serviceAccount := &corev1.ServiceAccount{}
|
serviceAccount := &corev1.ServiceAccount{}
|
||||||
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: meta.Name, Namespace: meta.Namespace}, serviceAccount)
|
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: meta.Name, Namespace: meta.Namespace}, serviceAccount)
|
||||||
|
annotations := r.Configuration.Jenkins.Spec.ServiceAccount.Annotations
|
||||||
|
msg := fmt.Sprintf("createServiceAccount with annotations %v", annotations)
|
||||||
|
r.logger.V(log.VDebug).Info(msg)
|
||||||
if err != nil && apierrors.IsNotFound(err) {
|
if err != nil && apierrors.IsNotFound(err) {
|
||||||
serviceAccount = resources.NewServiceAccount(meta, r.Configuration.Jenkins.Spec.ServiceAccount.Annotations)
|
serviceAccount = resources.NewServiceAccount(meta, annotations)
|
||||||
if err = r.CreateResource(serviceAccount); err != nil {
|
if err = r.CreateResource(serviceAccount); err != nil {
|
||||||
return stackerr.WithStack(err)
|
return stackerr.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
@ -24,11 +29,11 @@ func (r *ReconcileJenkinsBaseConfiguration) createServiceAccount(meta metav1.Obj
|
||||||
return stackerr.WithStack(err)
|
return stackerr.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !compareMap(r.Configuration.Jenkins.Spec.ServiceAccount.Annotations, serviceAccount.Annotations) {
|
if !compareMap(annotations, serviceAccount.Annotations) {
|
||||||
if serviceAccount.Annotations == nil {
|
if serviceAccount.Annotations == nil {
|
||||||
serviceAccount.Annotations = map[string]string{}
|
serviceAccount.Annotations = map[string]string{}
|
||||||
}
|
}
|
||||||
for key, value := range r.Configuration.Jenkins.Spec.ServiceAccount.Annotations {
|
for key, value := range annotations {
|
||||||
serviceAccount.Annotations[key] = value
|
serviceAccount.Annotations[key] = value
|
||||||
}
|
}
|
||||||
if err = r.UpdateResource(serviceAccount); err != nil {
|
if err = r.UpdateResource(serviceAccount); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
---
|
||||||
|
title: "OpenShift"
|
||||||
|
linkTitle: "OpenShift"
|
||||||
|
weight: 20
|
||||||
|
date: 2020-04-29
|
||||||
|
description: >
|
||||||
|
Additional configuration for OpenShift
|
||||||
|
---
|
||||||
|
|
||||||
|
## SecurityContext
|
||||||
|
|
||||||
|
OpenShift enforces Security Constraints Context (scc) when deploying an image.
|
||||||
|
By default, container images run in restricted scc which prevents from setting
|
||||||
|
a fixed user id to run with. You need to have ensure that you do not provide a
|
||||||
|
securityContext with a runAsUser and that your image does not use a hardcoded user.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
securityContext: {}
|
||||||
|
```
|
||||||
|
|
||||||
|
## OpenShift Jenkins image
|
||||||
|
|
||||||
|
OpenShift provides a pre-configured Jenkins image containing 3 openshift plugins for
|
||||||
|
jenkins (openshift-login-plugin, openshift-sync-plugin and openshift-client-plugin)
|
||||||
|
which allows better jenkins integration with kubernetes and OpenShift.
|
||||||
|
|
||||||
|
The OpenShift Jenkins image requires additional configuration to be fully enabled.
|
||||||
|
|
||||||
|
### Sample OpenShift CR
|
||||||
|
The following Custom Resource can be used to create a Jenkins instance using the
|
||||||
|
OpenShift Jenkins image and sets values for:
|
||||||
|
- `image: 'quay.io/openshift/origin-jenkins:latest' : This is the OpenShift Jenkins image.
|
||||||
|
|
||||||
|
- serviceAccount: to allow oauth authentication to work, the service account needs
|
||||||
|
a specific annotation pointing to the route exposing the jenkins service. Here,
|
||||||
|
the route is named `jenkins-route`
|
||||||
|
|
||||||
|
- `OPENSHIFT_ENABLE_OAUTH` environment variable for the master container is set to true.
|
||||||
|
|
||||||
|
Here is a complete Jenkins CR allowing the deployment of the Jenkins OpenShift image.
|
||||||
|
```yaml
|
||||||
|
apiVersion: jenkins.io/v1alpha2
|
||||||
|
kind: Jenkins
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
jenkins.io/openshift-mode: 'true'
|
||||||
|
name: jenkins
|
||||||
|
spec:
|
||||||
|
serviceAccount:
|
||||||
|
annotations:
|
||||||
|
serviceaccounts.openshift.io/oauth-redirectreference.jenkins: '{"kind":"OAuthRedirectReference","apiVersion":"v1","reference":{"kind":"Route","name":"jenkins-route"}}'
|
||||||
|
master:
|
||||||
|
containers:
|
||||||
|
- name: jenkins-master
|
||||||
|
image: 'quay.io/openshift/origin-jenkins:latest'
|
||||||
|
command:
|
||||||
|
- /usr/bin/go-init
|
||||||
|
- '-main'
|
||||||
|
- /usr/libexec/s2i/run
|
||||||
|
env:
|
||||||
|
- name: OPENSHIFT_ENABLE_OAUTH
|
||||||
|
value: 'true'
|
||||||
|
- name: OPENSHIFT_ENABLE_REDIRECT_PROMPT
|
||||||
|
value: 'true'
|
||||||
|
- name: DISABLE_ADMINISTRATIVE_MONITORS
|
||||||
|
value: 'false'
|
||||||
|
- name: KUBERNETES_MASTER
|
||||||
|
value: 'https://kubernetes.default:443'
|
||||||
|
- name: KUBERNETES_TRUST_CERTIFICATES
|
||||||
|
value: 'true'
|
||||||
|
- name: JENKINS_SERVICE_NAME
|
||||||
|
value: jenkins-operator-http-jenkins
|
||||||
|
- name: JNLP_SERVICE_NAME
|
||||||
|
value: jenkins-operator-slave-jenkins
|
||||||
|
- name: JENKINS_UC_INSECURE
|
||||||
|
value: 'false'
|
||||||
|
- name: JENKINS_HOME
|
||||||
|
value: /var/lib/jenkins
|
||||||
|
- name: JAVA_OPTS
|
||||||
|
value: >-
|
||||||
|
-XX:+UnlockExperimentalVMOptions -XX:+UnlockExperimentalVMOptions
|
||||||
|
-XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1
|
||||||
|
-Djenkins.install.runSetupWizard=false -Djava.awt.headless=true
|
||||||
|
imagePullPolicy: Always
|
||||||
|
service:
|
||||||
|
port: 8080
|
||||||
|
type: ClusterIP
|
||||||
|
slaveService:
|
||||||
|
port: 50000
|
||||||
|
type: ClusterIP
|
||||||
|
```
|
||||||
|
|
||||||
|
### OpenShift OAuth integration
|
||||||
|
The creation of a Route is required for the integraiton of Jenkins with
|
||||||
|
OpenShift oauth authentication. By default, the jenkins http service is named
|
||||||
|
`jenkins-operator-http-${jenkins-cr-name}`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
oc create route edge jenkins-route --service=jenkins-operator-http-jenkins
|
||||||
|
```
|
||||||
|
Note: the route name (jenkins-route) must match the pointed route on the serviceaccount annotation.
|
||||||
|
|
||||||
|
|
||||||
|
After the creation of the Route. It can be used to navigate to the Jenkins Login Page and login with your Openshift Credentials.
|
||||||
Loading…
Reference in New Issue