Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
8c49d1db
Commit
8c49d1db
authored
Nov 20, 2017
by
Hemant Kumar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement disk resizing for AWS
Update bazel files
parent
ccb15fb4
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
187 additions
and
1 deletion
+187
-1
BUILD
pkg/cloudprovider/providers/aws/BUILD
+1
-0
aws.go
pkg/cloudprovider/providers/aws/aws.go
+128
-0
aws_fakes.go
pkg/cloudprovider/providers/aws/aws_fakes.go
+8
-0
BUILD
pkg/volume/aws_ebs/BUILD
+1
-0
attacher_test.go
pkg/volume/aws_ebs/attacher_test.go
+8
-0
aws_ebs.go
pkg/volume/aws_ebs/aws_ebs.go
+27
-0
BUILD
plugin/pkg/admission/persistentvolume/label/BUILD
+1
-0
admission_test.go
...in/pkg/admission/persistentvolume/label/admission_test.go
+8
-0
admission.go
plugin/pkg/admission/persistentvolume/resize/admission.go
+5
-1
No files found.
pkg/cloudprovider/providers/aws/BUILD
View file @
8c49d1db
...
@@ -50,6 +50,7 @@ go_library(
...
@@ -50,6 +50,7 @@ go_library(
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
"//vendor/gopkg.in/gcfg.v1:go_default_library",
"//vendor/gopkg.in/gcfg.v1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
...
...
pkg/cloudprovider/providers/aws/aws.go
View file @
8c49d1db
...
@@ -48,6 +48,7 @@ import (
...
@@ -48,6 +48,7 @@ import (
"path"
"path"
"k8s.io/api/core/v1"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/sets"
...
@@ -285,6 +286,10 @@ type EC2 interface {
...
@@ -285,6 +286,10 @@ type EC2 interface {
// Delete an EBS volume
// Delete an EBS volume
DeleteVolume
(
*
ec2
.
DeleteVolumeInput
)
(
*
ec2
.
DeleteVolumeOutput
,
error
)
DeleteVolume
(
*
ec2
.
DeleteVolumeInput
)
(
*
ec2
.
DeleteVolumeOutput
,
error
)
ModifyVolume
(
*
ec2
.
ModifyVolumeInput
)
(
*
ec2
.
ModifyVolumeOutput
,
error
)
DescribeVolumeModifications
(
*
ec2
.
DescribeVolumesModificationsInput
)
([]
*
ec2
.
VolumeModification
,
error
)
DescribeSecurityGroups
(
request
*
ec2
.
DescribeSecurityGroupsInput
)
([]
*
ec2
.
SecurityGroup
,
error
)
DescribeSecurityGroups
(
request
*
ec2
.
DescribeSecurityGroupsInput
)
([]
*
ec2
.
SecurityGroup
,
error
)
CreateSecurityGroup
(
*
ec2
.
CreateSecurityGroupInput
)
(
*
ec2
.
CreateSecurityGroupOutput
,
error
)
CreateSecurityGroup
(
*
ec2
.
CreateSecurityGroupInput
)
(
*
ec2
.
CreateSecurityGroupOutput
,
error
)
...
@@ -453,6 +458,9 @@ type Volumes interface {
...
@@ -453,6 +458,9 @@ type Volumes interface {
// Check if disks specified in argument map are still attached to their respective nodes.
// Check if disks specified in argument map are still attached to their respective nodes.
DisksAreAttached
(
map
[
types
.
NodeName
][]
KubernetesVolumeID
)
(
map
[
types
.
NodeName
]
map
[
KubernetesVolumeID
]
bool
,
error
)
DisksAreAttached
(
map
[
types
.
NodeName
][]
KubernetesVolumeID
)
(
map
[
types
.
NodeName
]
map
[
KubernetesVolumeID
]
bool
,
error
)
// Expand the disk to new size
ResizeDisk
(
diskName
KubernetesVolumeID
,
oldSize
resource
.
Quantity
,
newSize
resource
.
Quantity
)
(
resource
.
Quantity
,
error
)
}
}
// InstanceGroups is an interface for managing cloud-managed instance groups / autoscaling instance groups
// InstanceGroups is an interface for managing cloud-managed instance groups / autoscaling instance groups
...
@@ -833,6 +841,36 @@ func (s *awsSdkEC2) DeleteVolume(request *ec2.DeleteVolumeInput) (*ec2.DeleteVol
...
@@ -833,6 +841,36 @@ func (s *awsSdkEC2) DeleteVolume(request *ec2.DeleteVolumeInput) (*ec2.DeleteVol
return
resp
,
err
return
resp
,
err
}
}
func
(
s
*
awsSdkEC2
)
ModifyVolume
(
request
*
ec2
.
ModifyVolumeInput
)
(
*
ec2
.
ModifyVolumeOutput
,
error
)
{
requestTime
:=
time
.
Now
()
resp
,
err
:=
s
.
ec2
.
ModifyVolume
(
request
)
timeTaken
:=
time
.
Since
(
requestTime
)
.
Seconds
()
recordAwsMetric
(
"modify_volume"
,
timeTaken
,
err
)
return
resp
,
err
}
func
(
s
*
awsSdkEC2
)
DescribeVolumeModifications
(
request
*
ec2
.
DescribeVolumesModificationsInput
)
([]
*
ec2
.
VolumeModification
,
error
)
{
requestTime
:=
time
.
Now
()
results
:=
[]
*
ec2
.
VolumeModification
{}
var
nextToken
*
string
for
{
resp
,
err
:=
s
.
ec2
.
DescribeVolumesModifications
(
request
)
if
err
!=
nil
{
recordAwsMetric
(
"describe_volume_modification"
,
0
,
err
)
return
nil
,
fmt
.
Errorf
(
"error listing volume modifictions : %v"
,
err
)
}
results
=
append
(
results
,
resp
.
VolumesModifications
...
)
nextToken
=
resp
.
NextToken
if
aws
.
StringValue
(
nextToken
)
==
""
{
break
}
request
.
NextToken
=
nextToken
}
timeTaken
:=
time
.
Since
(
requestTime
)
.
Seconds
()
recordAwsMetric
(
"describe_volume_modification"
,
timeTaken
,
nil
)
return
results
,
nil
}
func
(
s
*
awsSdkEC2
)
DescribeSubnets
(
request
*
ec2
.
DescribeSubnetsInput
)
([]
*
ec2
.
Subnet
,
error
)
{
func
(
s
*
awsSdkEC2
)
DescribeSubnets
(
request
*
ec2
.
DescribeSubnetsInput
)
([]
*
ec2
.
Subnet
,
error
)
{
// Subnets are not paged
// Subnets are not paged
response
,
err
:=
s
.
ec2
.
DescribeSubnets
(
request
)
response
,
err
:=
s
.
ec2
.
DescribeSubnets
(
request
)
...
@@ -1653,6 +1691,65 @@ func (d *awsDisk) describeVolume() (*ec2.Volume, error) {
...
@@ -1653,6 +1691,65 @@ func (d *awsDisk) describeVolume() (*ec2.Volume, error) {
return
volumes
[
0
],
nil
return
volumes
[
0
],
nil
}
}
func
(
d
*
awsDisk
)
describeVolumeModification
()
(
*
ec2
.
VolumeModification
,
error
)
{
volumeID
:=
d
.
awsID
request
:=
&
ec2
.
DescribeVolumesModificationsInput
{
VolumeIds
:
[]
*
string
{
volumeID
.
awsString
()},
}
volumeMods
,
err
:=
d
.
ec2
.
DescribeVolumeModifications
(
request
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error describing volume modification %s with %v"
,
volumeID
,
err
)
}
if
len
(
volumeMods
)
==
0
{
return
nil
,
fmt
.
Errorf
(
"no volume modifications found for %s"
,
volumeID
)
}
lastIndex
:=
len
(
volumeMods
)
-
1
return
volumeMods
[
lastIndex
],
nil
}
func
(
d
*
awsDisk
)
modifyVolume
(
requestGiB
int64
)
(
int64
,
error
)
{
volumeID
:=
d
.
awsID
request
:=
&
ec2
.
ModifyVolumeInput
{
VolumeId
:
volumeID
.
awsString
(),
Size
:
aws
.
Int64
(
requestGiB
),
}
output
,
err
:=
d
.
ec2
.
ModifyVolume
(
request
)
if
err
!=
nil
{
modifyError
:=
fmt
.
Errorf
(
"AWS modifyVolume failed for %s with %v"
,
volumeID
,
err
)
return
requestGiB
,
modifyError
}
volumeModification
:=
output
.
VolumeModification
if
aws
.
StringValue
(
volumeModification
.
ModificationState
)
==
ec2
.
VolumeModificationStateCompleted
{
return
aws
.
Int64Value
(
volumeModification
.
TargetSize
),
nil
}
backoff
:=
wait
.
Backoff
{
Duration
:
1
*
time
.
Second
,
Factor
:
2
,
Steps
:
10
,
}
checkForResize
:=
func
()
(
bool
,
error
)
{
volumeModification
,
err
:=
d
.
describeVolumeModification
()
if
err
!=
nil
{
return
false
,
err
}
if
aws
.
StringValue
(
volumeModification
.
ModificationState
)
==
ec2
.
VolumeModificationStateCompleted
{
return
true
,
nil
}
return
false
,
nil
}
waitWithErr
:=
wait
.
ExponentialBackoff
(
backoff
,
checkForResize
)
return
requestGiB
,
waitWithErr
}
// applyUnSchedulableTaint applies a unschedulable taint to a node after verifying
// applyUnSchedulableTaint applies a unschedulable taint to a node after verifying
// if node has become unusable because of volumes getting stuck in attaching state.
// if node has become unusable because of volumes getting stuck in attaching state.
func
(
c
*
Cloud
)
applyUnSchedulableTaint
(
nodeName
types
.
NodeName
,
reason
string
)
{
func
(
c
*
Cloud
)
applyUnSchedulableTaint
(
nodeName
types
.
NodeName
,
reason
string
)
{
...
@@ -2321,6 +2418,37 @@ func (c *Cloud) DisksAreAttached(nodeDisks map[types.NodeName][]KubernetesVolume
...
@@ -2321,6 +2418,37 @@ func (c *Cloud) DisksAreAttached(nodeDisks map[types.NodeName][]KubernetesVolume
return
attached
,
nil
return
attached
,
nil
}
}
func
(
c
*
Cloud
)
ResizeDisk
(
diskName
KubernetesVolumeID
,
oldSize
resource
.
Quantity
,
newSize
resource
.
Quantity
)
(
resource
.
Quantity
,
error
)
{
awsDisk
,
err
:=
newAWSDisk
(
c
,
diskName
)
if
err
!=
nil
{
return
oldSize
,
err
}
volumeInfo
,
err
:=
awsDisk
.
describeVolume
()
if
err
!=
nil
{
descErr
:=
fmt
.
Errorf
(
"AWS.ResizeDisk Error describing volume %s with %v"
,
diskName
,
err
)
return
oldSize
,
descErr
}
requestBytes
:=
newSize
.
Value
()
// AWS resizes in chunks of GiB (not GB)
requestGiB
:=
volume
.
RoundUpSize
(
requestBytes
,
1024
*
1024
*
1024
)
newSizeQuant
:=
resource
.
MustParse
(
fmt
.
Sprintf
(
"%dGi"
,
requestGiB
))
// If disk already if of greater or equal size than requested we return
if
aws
.
Int64Value
(
volumeInfo
.
Size
)
>=
requestGiB
{
return
newSizeQuant
,
nil
}
_
,
err
=
awsDisk
.
modifyVolume
(
requestGiB
)
if
err
!=
nil
{
return
oldSize
,
err
}
return
newSizeQuant
,
nil
}
// Gets the current load balancer state
// Gets the current load balancer state
func
(
c
*
Cloud
)
describeLoadBalancer
(
name
string
)
(
*
elb
.
LoadBalancerDescription
,
error
)
{
func
(
c
*
Cloud
)
describeLoadBalancer
(
name
string
)
(
*
elb
.
LoadBalancerDescription
,
error
)
{
request
:=
&
elb
.
DescribeLoadBalancersInput
{}
request
:=
&
elb
.
DescribeLoadBalancersInput
{}
...
...
pkg/cloudprovider/providers/aws/aws_fakes.go
View file @
8c49d1db
...
@@ -203,6 +203,14 @@ func (ec2i *FakeEC2Impl) RevokeSecurityGroupIngress(*ec2.RevokeSecurityGroupIngr
...
@@ -203,6 +203,14 @@ func (ec2i *FakeEC2Impl) RevokeSecurityGroupIngress(*ec2.RevokeSecurityGroupIngr
panic
(
"Not implemented"
)
panic
(
"Not implemented"
)
}
}
func
(
ec2i
*
FakeEC2Impl
)
DescribeVolumeModifications
(
*
ec2
.
DescribeVolumesModificationsInput
)
([]
*
ec2
.
VolumeModification
,
error
)
{
panic
(
"Not implemented"
)
}
func
(
ec2i
*
FakeEC2Impl
)
ModifyVolume
(
*
ec2
.
ModifyVolumeInput
)
(
*
ec2
.
ModifyVolumeOutput
,
error
)
{
panic
(
"Not implemented"
)
}
func
(
ec2i
*
FakeEC2Impl
)
CreateSubnet
(
request
*
ec2
.
Subnet
)
(
*
ec2
.
CreateSubnetOutput
,
error
)
{
func
(
ec2i
*
FakeEC2Impl
)
CreateSubnet
(
request
*
ec2
.
Subnet
)
(
*
ec2
.
CreateSubnetOutput
,
error
)
{
ec2i
.
Subnets
=
append
(
ec2i
.
Subnets
,
request
)
ec2i
.
Subnets
=
append
(
ec2i
.
Subnets
,
request
)
response
:=
&
ec2
.
CreateSubnetOutput
{
response
:=
&
ec2
.
CreateSubnetOutput
{
...
...
pkg/volume/aws_ebs/BUILD
View file @
8c49d1db
...
@@ -46,6 +46,7 @@ go_test(
...
@@ -46,6 +46,7 @@ go_test(
"//pkg/volume/testing:go_default_library",
"//pkg/volume/testing:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/fake:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/fake:go_default_library",
...
...
pkg/volume/aws_ebs/attacher_test.go
View file @
8c49d1db
...
@@ -26,6 +26,7 @@ import (
...
@@ -26,6 +26,7 @@ import (
volumetest
"k8s.io/kubernetes/pkg/volume/testing"
volumetest
"k8s.io/kubernetes/pkg/volume/testing"
"github.com/golang/glog"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/types"
)
)
...
@@ -340,3 +341,10 @@ func (testcase *testcase) GetVolumeLabels(volumeName aws.KubernetesVolumeID) (ma
...
@@ -340,3 +341,10 @@ func (testcase *testcase) GetVolumeLabels(volumeName aws.KubernetesVolumeID) (ma
func
(
testcase
*
testcase
)
GetDiskPath
(
volumeName
aws
.
KubernetesVolumeID
)
(
string
,
error
)
{
func
(
testcase
*
testcase
)
GetDiskPath
(
volumeName
aws
.
KubernetesVolumeID
)
(
string
,
error
)
{
return
""
,
errors
.
New
(
"Not implemented"
)
return
""
,
errors
.
New
(
"Not implemented"
)
}
}
func
(
testcase
*
testcase
)
ResizeDisk
(
volumeName
aws
.
KubernetesVolumeID
,
oldSize
resource
.
Quantity
,
newSize
resource
.
Quantity
)
(
resource
.
Quantity
,
error
)
{
return
oldSize
,
errors
.
New
(
"Not implemented"
)
}
pkg/volume/aws_ebs/aws_ebs.go
View file @
8c49d1db
...
@@ -241,6 +241,33 @@ func (plugin *awsElasticBlockStorePlugin) ConstructVolumeSpec(volName, mountPath
...
@@ -241,6 +241,33 @@ func (plugin *awsElasticBlockStorePlugin) ConstructVolumeSpec(volName, mountPath
return
volume
.
NewSpecFromVolume
(
awsVolume
),
nil
return
volume
.
NewSpecFromVolume
(
awsVolume
),
nil
}
}
func
(
plugin
*
awsElasticBlockStorePlugin
)
RequiresFSResize
()
bool
{
return
true
}
func
(
plugin
*
awsElasticBlockStorePlugin
)
ExpandVolumeDevice
(
spec
*
volume
.
Spec
,
newSize
resource
.
Quantity
,
oldSize
resource
.
Quantity
)
(
resource
.
Quantity
,
error
)
{
var
awsVolume
aws
.
Volumes
awsVolume
,
err
:=
getCloudProvider
(
plugin
.
host
.
GetCloudProvider
())
if
err
!=
nil
{
return
oldSize
,
err
}
// we don't expect to receive this call for non PVs
rawVolumeName
:=
spec
.
PersistentVolume
.
Spec
.
AWSElasticBlockStore
.
VolumeID
volumeID
:=
aws
.
KubernetesVolumeID
(
rawVolumeName
)
if
volumeID
==
""
{
return
oldSize
,
fmt
.
Errorf
(
"EBS.ExpandVolumeDevice Invalid volume id for %s"
,
spec
.
Name
())
}
return
awsVolume
.
ResizeDisk
(
volumeID
,
oldSize
,
newSize
)
}
var
_
volume
.
ExpandableVolumePlugin
=
&
awsElasticBlockStorePlugin
{}
// Abstract interface to PD operations.
// Abstract interface to PD operations.
type
ebsManager
interface
{
type
ebsManager
interface
{
CreateVolume
(
provisioner
*
awsElasticBlockStoreProvisioner
)
(
volumeID
aws
.
KubernetesVolumeID
,
volumeSizeGB
int
,
labels
map
[
string
]
string
,
fstype
string
,
err
error
)
CreateVolume
(
provisioner
*
awsElasticBlockStoreProvisioner
)
(
volumeID
aws
.
KubernetesVolumeID
,
volumeSizeGB
int
,
labels
map
[
string
]
string
,
fstype
string
,
err
error
)
...
...
plugin/pkg/admission/persistentvolume/label/BUILD
View file @
8c49d1db
...
@@ -34,6 +34,7 @@ go_test(
...
@@ -34,6 +34,7 @@ go_test(
deps = [
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/cloudprovider/providers/aws:go_default_library",
"//pkg/cloudprovider/providers/aws:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
...
...
plugin/pkg/admission/persistentvolume/label/admission_test.go
View file @
8c49d1db
...
@@ -21,6 +21,7 @@ import (
...
@@ -21,6 +21,7 @@ import (
"fmt"
"fmt"
"k8s.io/apimachinery/pkg/api/resource"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission"
...
@@ -67,6 +68,13 @@ func (c *mockVolumes) DisksAreAttached(nodeDisks map[types.NodeName][]aws.Kubern
...
@@ -67,6 +68,13 @@ func (c *mockVolumes) DisksAreAttached(nodeDisks map[types.NodeName][]aws.Kubern
return
nil
,
fmt
.
Errorf
(
"not implemented"
)
return
nil
,
fmt
.
Errorf
(
"not implemented"
)
}
}
func
(
c
*
mockVolumes
)
ResizeDisk
(
diskName
aws
.
KubernetesVolumeID
,
oldSize
resource
.
Quantity
,
newSize
resource
.
Quantity
)
(
resource
.
Quantity
,
error
)
{
return
oldSize
,
nil
}
func
mockVolumeFailure
(
err
error
)
*
mockVolumes
{
func
mockVolumeFailure
(
err
error
)
*
mockVolumes
{
return
&
mockVolumes
{
volumeLabelsError
:
err
}
return
&
mockVolumes
{
volumeLabelsError
:
err
}
}
}
...
...
plugin/pkg/admission/persistentvolume/resize/admission.go
View file @
8c49d1db
...
@@ -159,6 +159,10 @@ func (pvcr *persistentVolumeClaimResize) checkVolumePlugin(pv *api.PersistentVol
...
@@ -159,6 +159,10 @@ func (pvcr *persistentVolumeClaimResize) checkVolumePlugin(pv *api.PersistentVol
if
pv
.
Spec
.
GCEPersistentDisk
!=
nil
{
if
pv
.
Spec
.
GCEPersistentDisk
!=
nil
{
return
true
return
true
}
}
return
false
if
pv
.
Spec
.
AWSElasticBlockStore
!=
nil
{
return
true
}
return
false
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment