-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support the multiple network when creating Pod #111
Changes from 13 commits
34065f0
a9d69a4
8f22b48
80fdb01
a2ce9ed
2c30e1e
f46d87d
8f76e91
d18e645
b8e4c08
588676c
4898db7
4ca8f17
26e3e82
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,15 @@ type Container struct { | |
Command []string `bson:"command" json:"command" validate:"required,dive,required"` | ||
} | ||
|
||
type PodNetwork struct { | ||
Name string `bson:"name" json:"name"` | ||
IFName string `bson:"ifName" json:"ifName"` | ||
VLAN int `bson:"vlan" json:"vlan"` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
IPAddress string `bson:"ipAddress json:"ipAddress"` | ||
Netmask string `bson:"netmask" json:"netmask"` | ||
BridgeName string `bson:"bridgeName" json:"bridgeName"` //its from the entity.Network entity | ||
} | ||
|
||
type PodVolume struct { | ||
Name string `bson:"name" json:"name" validate:"required"` | ||
MountPath string `bson:"mountPath" json:"mountPath" validate:"required"` | ||
|
@@ -27,8 +36,9 @@ type Pod struct { | |
Namespace string `bson:"namespace" json:"namespace" validate:"required"` | ||
Labels map[string]string `bson:"labels,omitempty" json:"labels" validate:"required,dive,keys,alphanum,endkeys,required,alphanum"` | ||
Containers []Container `bson:"containers" json:"containers" validate:"required,dive,required"` | ||
Volumes []PodVolume `bson:"volumes,omitempty" json:"volumes" validate:"required,dive,required"` | ||
CreatedAt *time.Time `bson:"createdAt,omitempty" json:"createdAt,omitempty" validate:"-"` | ||
Volumes []PodVolume `bson:"volumes,omitempty" json:"volumes" validate:"required,dive,required"` | ||
Networks []PodNetwork `bson:"networks,omitempty" json:"networks validate:"required,dive,required"` | ||
} | ||
|
||
//GetCollection - get model mongo collection name. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ import ( | |
"github.com/linkernetworks/mongo" | ||
"github.com/linkernetworks/vortex/src/entity" | ||
"github.com/linkernetworks/vortex/src/serviceprovider" | ||
"github.com/linkernetworks/vortex/src/utils" | ||
|
||
corev1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
|
@@ -46,6 +47,17 @@ func CheckPodParameter(sp *serviceprovider.Container, pod *entity.Pod) error { | |
return fmt.Errorf("The volume name %s doesn't exist", v.Name) | ||
} | ||
} | ||
|
||
//Check the network | ||
for _, v := range pod.Networks { | ||
count, err := session.Count(entity.NetworkCollectionName, bson.M{"name": v.Name}) | ||
if err != nil { | ||
return fmt.Errorf("check the network name error:%v", err) | ||
} else if count == 0 { | ||
return fmt.Errorf("the network name %s doesn't exist", v.Name) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the network named %s doesn't exist |
||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
|
@@ -79,6 +91,123 @@ func generateVolume(pod *entity.Pod, session *mongo.Session) ([]corev1.Volume, [ | |
return volumes, volumeMounts, nil | ||
} | ||
|
||
//Get the intersecion of nodes' name | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Intersection |
||
func generateNodeLabels(networks []entity.Network) []string { | ||
totalNames := [][]string{} | ||
for _, network := range networks { | ||
names := []string{} | ||
for _, node := range network.Nodes { | ||
names = append(names, node.Name) | ||
} | ||
|
||
totalNames = append(totalNames, names) | ||
} | ||
|
||
return utils.Intersections(totalNames) | ||
} | ||
|
||
func generateClientCommand(network entity.PodNetwork) []string { | ||
ip := utils.IPToCIDR(network.IPAddress, network.Netmask) | ||
|
||
return []string{ | ||
"-s=unix:///tmp/vortex.sock", | ||
"-b=" + network.BridgeName, | ||
"-n=" + network.IFName, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
"-i=" + ip, | ||
} | ||
} | ||
|
||
func generateInitContainer(networks []entity.PodNetwork) ([]corev1.Container, error) { | ||
containers := []corev1.Container{} | ||
|
||
for i, v := range networks { | ||
containers = append(containers, corev1.Container{ | ||
Name: fmt.Sprintf("init-network-client-%d", i), | ||
Image: "sdnvortex/network-controller:latest", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 先固定在 v0.2.1? |
||
Command: []string{"/go/bin/client"}, | ||
Args: generateClientCommand(v), | ||
Env: []corev1.EnvVar{ | ||
{ | ||
Name: "POD_NAME", | ||
ValueFrom: &corev1.EnvVarSource{ | ||
FieldRef: &corev1.ObjectFieldSelector{ | ||
FieldPath: "metadata.name", | ||
}, | ||
}, | ||
}, | ||
{ | ||
Name: "POD_NAMESPACE", | ||
ValueFrom: &corev1.EnvVarSource{ | ||
FieldRef: &corev1.ObjectFieldSelector{ | ||
FieldPath: "metadata.namespace", | ||
}, | ||
}, | ||
}, | ||
{ | ||
Name: "POD_UUID", | ||
ValueFrom: &corev1.EnvVarSource{ | ||
FieldRef: &corev1.ObjectFieldSelector{ | ||
FieldPath: "metadata.uid", | ||
}, | ||
}, | ||
}, | ||
}, | ||
VolumeMounts: []corev1.VolumeMount{ | ||
{ | ||
Name: "grpc-sock", | ||
MountPath: "/tmp/", | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
return containers, nil | ||
} | ||
|
||
//For the network, we will generate two thins | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. things |
||
//[]string => a list of nodes and it will apply on nodeaffinity | ||
//[]corev1.Container => a list of init container we will apply on pod | ||
func generateNetwork(pod *entity.Pod, session *mongo.Session) ([]string, []corev1.Container, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. session *mongo.Session 可以放第一個嗎 |
||
|
||
networks := []entity.Network{} | ||
containers := []corev1.Container{} | ||
for i, v := range pod.Networks { | ||
network := entity.Network{} | ||
if err := session.FindOne(entity.NetworkCollectionName, bson.M{"name": v.Name}, &network); err != nil { | ||
return nil, nil, err | ||
} | ||
networks = append(networks, network) | ||
pod.Networks[i].BridgeName = network.BridgeName | ||
} | ||
|
||
nodes := generateNodeLabels(networks) | ||
containers, err := generateInitContainer(pod.Networks) | ||
return nodes, containers, err | ||
} | ||
|
||
func generateAffinity(nodeNames []string) *corev1.Affinity { | ||
if len(nodeNames) == 0 { | ||
return &corev1.Affinity{} | ||
} | ||
return &corev1.Affinity{ | ||
NodeAffinity: &corev1.NodeAffinity{ | ||
RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ | ||
NodeSelectorTerms: []corev1.NodeSelectorTerm{ | ||
{ | ||
MatchExpressions: []corev1.NodeSelectorRequirement{ | ||
{ | ||
Key: "kubernetes.io/hostname", | ||
Values: nodeNames, | ||
Operator: corev1.NodeSelectorOpIn, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func CreatePod(sp *serviceprovider.Container, pod *entity.Pod) error { | ||
session := sp.Mongo.NewSession() | ||
defer session.Close() | ||
|
@@ -88,6 +217,20 @@ func CreatePod(sp *serviceprovider.Container, pod *entity.Pod) error { | |
return err | ||
} | ||
|
||
nodeNames, initContainers, err := generateNetwork(pod, session) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
volumes = append(volumes, corev1.Volume{ | ||
Name: "grpc-sock", | ||
VolumeSource: corev1.VolumeSource{ | ||
HostPath: &corev1.HostPathVolumeSource{ | ||
Path: "/tmp/vortex", | ||
}, | ||
}, | ||
}) | ||
|
||
var containers []corev1.Container | ||
for _, container := range pod.Containers { | ||
containers = append(containers, corev1.Container{ | ||
|
@@ -104,10 +247,13 @@ func CreatePod(sp *serviceprovider.Container, pod *entity.Pod) error { | |
Labels: pod.Labels, | ||
}, | ||
Spec: corev1.PodSpec{ | ||
Containers: containers, | ||
Volumes: volumes, | ||
InitContainers: initContainers, | ||
Containers: containers, | ||
Volumes: volumes, | ||
Affinity: generateAffinity(nodeNames), | ||
}, | ||
} | ||
|
||
if pod.Namespace == "" { | ||
pod.Namespace = "default" | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IfName