Skip to content
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

Merged
merged 14 commits into from
Jul 18, 2018
12 changes: 11 additions & 1 deletion src/entity/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IfName

VLAN int `bson:"vlan" json:"vlan"`
Copy link
Contributor

@John-Lin John-Lin Jul 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vlanTag       int32    `bson:"vlanTag" json:"vlanTag"`

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"`
Expand All @@ -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.
Expand Down
150 changes: 148 additions & 2 deletions src/pod/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the network named %s doesn't exist

}
}

return nil
}

Expand Down Expand Up @@ -79,6 +91,123 @@ func generateVolume(pod *entity.Pod, session *mongo.Session) ([]corev1.Volume, [
return volumes, volumeMounts, nil
}

//Get the intersecion of nodes' name
Copy link
Contributor

@WakeupTsai WakeupTsai Jul 18, 2018

Choose a reason for hiding this comment

The 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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ifName

"-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",
Copy link
Contributor

Choose a reason for hiding this comment

The 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
Copy link
Contributor

Choose a reason for hiding this comment

The 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) {
Copy link
Contributor

Choose a reason for hiding this comment

The 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()
Expand All @@ -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{
Expand All @@ -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"
}
Expand Down
Loading